Graphene neighbor-shell hoppings#

This graphene model calculation illustrates a case where one can use TBModel.set_shell_hops to set the n’th nearest neighbor hoppings.

from pythtb import TBModel, Lattice
import numpy as np
lat_vecs = [[1, 0], [1 / 2, np.sqrt(3) / 2]]
orb_vecs = [[1 / 3, 1 / 3], [2 / 3, 2 / 3]]

lat = Lattice(lat_vecs, orb_vecs, periodic_dirs=[0, 1])

First nearest neighbor hopping#

For reference, we first create a graphene tight-binding model with only nearest neighbor hoppings.

nn_model = TBModel(lat)

shell_hops = {1: -np.exp(-1)}
nn_model.set_shell_hops(shell_hops=shell_hops, mode="set")
nn_model.visualize()
(<Figure size 800x800 with 1 Axes>, <Axes: xlabel='x', ylabel='y'>)
../_images/bab75707e0a607dee76e4011d1c06c480cbfa0f757ae915b83c352431e3271ff.png

N’th neighbor hopping#

We will now create a graphene tight-binding model and set the hopping amplitudes for the first five nearest neighbors. To do this we will use the set_shell_hops method of the TBModel class. This method takes a dictionary of the form {shell: amp} where the keys are the shell numbers (1 for nearest neighbor, 2 for next nearest neighbor, etc.) and the values are the hopping amplitudes.

model = TBModel(lat)

shells = list(range(1, 6))
shell_hops = {i: -np.exp(-i) for i in shells}  # exponentially decreasing hoppings
model.set_shell_hops(shell_hops=shell_hops, mode="set")

print(model)

Hide code cell output

----------------------------------------
       Tight-binding model report       
----------------------------------------
r-space dimension           = 2
k-space dimension           = 2
periodic directions         = [0, 1]
spinful                     = False
number of spin components   = 1
number of electronic states = 2
number of orbitals          = 2

Lattice vectors (Cartesian):
  # 0 ===> [ 1.000,  0.000]
  # 1 ===> [ 0.500,  0.866]
Volume of unit cell (Cartesian) = 0.866 [A^d]

Reciprocal lattice vectors (Cartesian):
  # 0 ===> [ 6.283, -3.628]
  # 1 ===> [ 0.000,  7.255]
Volume of reciprocal unit cell = 45.586 [A^-d]

Orbital vectors (Cartesian):
  # 0 ===> [ 0.500,  0.289]
  # 1 ===> [ 1.000,  0.577]

Orbital vectors (fractional):
  # 0 ===> [ 0.333,  0.333]
  # 1 ===> [ 0.667,  0.667]
----------------------------------------
Site energies:
  < 0 | H | 0 > =  0.000 
  < 1 | H | 1 > =  0.000 
Hoppings:
  < 1 | H | 0  + [ 1.0 ,  0.0 ] > = -0.3679+0.0000j
  < 1 | H | 0  + [ 0.0 ,  0.0 ] > = -0.3679+0.0000j
  < 0 | H | 1  + [ 0.0 , -1.0 ] > = -0.3679+0.0000j
  < 1 | H | 1  + [-1.0 ,  1.0 ] > = -0.1353+0.0000j
  < 1 | H | 1  + [ 1.0 ,  0.0 ] > = -0.1353+0.0000j
  < 0 | H | 0  + [ 0.0 , -1.0 ] > = -0.1353+0.0000j
  < 0 | H | 0  + [ 1.0 , -1.0 ] > = -0.1353+0.0000j
  < 1 | H | 1  + [ 0.0 , -1.0 ] > = -0.1353+0.0000j
  < 0 | H | 0  + [ 1.0 ,  0.0 ] > = -0.1353+0.0000j
  < 1 | H | 0  + [-1.0 ,  1.0 ] > = -0.0498+0.0000j
  < 1 | H | 0  + [ 1.0 , -1.0 ] > = -0.0498+0.0000j
  < 0 | H | 1  + [-1.0 , -1.0 ] > = -0.0498+0.0000j
  < 0 | H | 1  + [ 1.0 ,  0.0 ] > = -0.0183+0.0000j
  < 1 | H | 0  + [-1.0 ,  2.0 ] > = -0.0183+0.0000j
  < 1 | H | 0  + [ 2.0 , -1.0 ] > = -0.0183+0.0000j
  < 0 | H | 1  + [ 0.0 , -2.0 ] > = -0.0183+0.0000j
  < 0 | H | 1  + [-2.0 ,  0.0 ] > = -0.0183+0.0000j
  < 1 | H | 0  + [ 0.0 , -1.0 ] > = -0.0183+0.0000j
  < 1 | H | 1  + [-1.0 , -1.0 ] > = -0.0067+0.0000j
  < 1 | H | 1  + [-2.0 ,  1.0 ] > = -0.0067+0.0000j
  < 0 | H | 0  + [ 1.0 , -2.0 ] > = -0.0067+0.0000j
  < 0 | H | 0  + [-1.0 , -1.0 ] > = -0.0067+0.0000j
  < 1 | H | 1  + [ 1.0 , -2.0 ] > = -0.0067+0.0000j
  < 0 | H | 0  + [ 2.0 , -1.0 ] > = -0.0067+0.0000j
Hopping distances:
  | pos( 1 ) - pos( 0 ) + [ 1.0 ,  0.0 ] | =   0.577
  | pos( 1 ) - pos( 0 ) + [ 0.0 ,  0.0 ] | =   0.577
  | pos( 0 ) - pos( 1 ) + [ 0.0 , -1.0 ] | =   0.577
  | pos( 1 ) - pos( 1 ) + [-1.0 ,  1.0 ] | =   1.000
  | pos( 1 ) - pos( 1 ) + [ 1.0 ,  0.0 ] | =   1.000
  | pos( 0 ) - pos( 0 ) + [ 0.0 , -1.0 ] | =   1.000
  | pos( 0 ) - pos( 0 ) + [ 1.0 , -1.0 ] | =   1.000
  | pos( 1 ) - pos( 1 ) + [ 0.0 , -1.0 ] | =   1.000
  | pos( 0 ) - pos( 0 ) + [ 1.0 ,  0.0 ] | =   1.000
  | pos( 1 ) - pos( 0 ) + [-1.0 ,  1.0 ] | =   1.155
  | pos( 1 ) - pos( 0 ) + [ 1.0 , -1.0 ] | =   1.155
  | pos( 0 ) - pos( 1 ) + [-1.0 , -1.0 ] | =   1.155
  | pos( 0 ) - pos( 1 ) + [ 1.0 ,  0.0 ] | =   1.528
  | pos( 1 ) - pos( 0 ) + [-1.0 ,  2.0 ] | =   1.528
  | pos( 1 ) - pos( 0 ) + [ 2.0 , -1.0 ] | =   1.528
  | pos( 0 ) - pos( 1 ) + [ 0.0 , -2.0 ] | =   1.528
  | pos( 0 ) - pos( 1 ) + [-2.0 ,  0.0 ] | =   1.528
  | pos( 1 ) - pos( 0 ) + [ 0.0 , -1.0 ] | =   1.528
  | pos( 1 ) - pos( 1 ) + [-1.0 , -1.0 ] | =   1.732
  | pos( 1 ) - pos( 1 ) + [-2.0 ,  1.0 ] | =   1.732
  | pos( 0 ) - pos( 0 ) + [ 1.0 , -2.0 ] | =   1.732
  | pos( 0 ) - pos( 0 ) + [-1.0 , -1.0 ] | =   1.732
  | pos( 1 ) - pos( 1 ) + [ 1.0 , -2.0 ] | =   1.732
  | pos( 0 ) - pos( 0 ) + [ 2.0 , -1.0 ] | =   1.732

The visualize method will allow us to see the connectivity of the model after setting the hoppings.

model.visualize()
(<Figure size 800x800 with 1 Axes>, <Axes: xlabel='x', ylabel='y'>)
../_images/eb523d3de90caa8f4fa57a5c5d336fedfa2c0adac0f6855654ae1d68b7e704f4.png

Band stucture with shells up to 5th nearest neighbor#

We now compute the band structure of graphene while progressively including hopping terms out to the 5th nearest neighbor shell. Each additional shell introduces corrections beyond the ideal nearest-neighbor model. In particular:

  • 2nd-neighbor hoppings generate same-sublattice terms that break particle–hole symmetry,

  • 3rd and 4th shells distort the Dirac cone and modify the trigonal warping,

  • higher shells potentially recover more realistic quantitative dispersions.

By comparing band structures with 1, 3, and 5 shells, we can directly visualize how distant-neighbor interactions reshape the dispersion and lift the artificial symmetries of the minimal tight-binding model.

path = [[0, 0], [2 / 3, 1 / 3], [1 / 2, 1 / 2], [0, 0]]
label = (r"$\Gamma $", r"$K$", r"$M$", r"$\Gamma $")
nk = 100

fig, ax = nn_model.plot_bands(path, label, nk, bands_label="NN", fig=None, ax=None)
model.plot_bands(
    path, label, nk, bands_label=f"{max(shells)}'th NN", fig=fig, ax=ax, ls="--", lc="r"
)
ax.set_title("Graphene Tight-Binding Model")
Text(0.5, 1.0, 'Graphene Tight-Binding Model')
../_images/763e7bfcfd58c39dbe17c58df09409b4d1b0738e8f51d1d9038104e7833f79ec.png

Band structure using only odd neighbor shells#

For comparison, we repeat the calculation while including only odd-indexed neighbor shells (1st, 3rd, 5th). These hoppings connect opposite sublattices and therefore preserve the particle-hole symmetry of the idealized graphene Dirac spectrum.

Because even shells (especially 2nd neighbors) introduce same-sublattice hoppings that break particle–hole symmetry, the odd-shell-only model retains a band structure that remains closer to the idealized symmetric Dirac spectrum. By examining the differences between this restricted model and the full shell expansion, we can isolate the specific role of even-shell hoppings in distorting and shifting the Dirac point.

model = TBModel(lat)

shells = [1, 3, 5, 7, 9]
shell_hops = {i: -np.exp(-i) for i in shells}  # exponentially decreasing hoppings
model.set_shell_hops(shell_hops=shell_hops, mode="set")

fig, ax = nn_model.plot_bands(path, label, nk, bands_label="NN", fig=None, ax=None)
model.plot_bands(
    path,
    label,
    nk,
    bands_label=f"Odd shell hoppings up to {max(shells)}'th NN",
    fig=fig,
    ax=ax,
    ls="--",
    lc="r",
)
ax.set_title("Graphene Tight-Binding Model")
Text(0.5, 1.0, 'Graphene Tight-Binding Model')
../_images/cfbb315243c13ae8a5b1886cb8571de47179396485112349557e7a88e9354290.png