Twisted bilayer graphene (in-built methods)¶
A common way to describe a moire system is using the 4 indices defined by Hermann.
Tasks: - Create a twisted bilayer system using the 31 30 30 31
indices and visualize the structure. - Calculate the electronic bandstructure and visualize the flat band. - Calculate the Lancoz DOS and optimize the supercell size to get clear signatures. Note that the TB model we use includes a large number of neighbors, because of this, the memory requirements are much larger than in our previous session where we only include 3 neighbors in the GBN effective model calculations. For the sake
of this session, consider small cells (i.e. SuperCell 5
that can still be calculated easily on the mem128 machines). You can go up to SuperCell 20
if you use one of the large memory machines. - Compare the previous DOS with the DOS calculated by exact diagonalization. Reminder: the Lancos DOS has been renormalized by the number of atoms. To match it with the diagonalization DOS, one needs to multiply Lanczos DOS by the number of two times the number of atoms and divide it by the first
nearest neighbor hopping (check TB.Hopping
value in your input file). The energy axis is also given in units of the first nearest neighbor hopping. - Add Anderson disorder to your system and see how it affects the DOS. - Add a magnetic field and compare the DOS in presence and absence of disorder. Can you explain what you see based on your knowledge of Landau levels?
tBG(read from external file, i.e. use ReadXYZ)¶
Repeat the twisted bilayer graphene calculations from the previous section using the relaxed structure given for download here.
Compare the results for the previous rigid configuration with the relaxed configuration observables.
Twisted bilayer graphene on hBN (bonus)¶
Try to combine the knowledge from previous session with the knowledge from current session to simulate the same observables for tBG on hBN. Note that for exact diagonalization calculations, a commensurate cell is required. You can avoid this complication when considering very large supercells for Lanczos where the periodic boundary effects become increasingly negligible.
[ ]:
Code snippets¶
Some routines¶
[1]:
import numpy as np
import matplotlib.pyplot as plt
import os
def latexify(fig_width=None, fig_height=None, columns=1):
"""Set up matplotlib's RC params for LaTeX plotting.
Call this before plotting a figure.
Parameters
----------
fig_width : float, optional, inches
fig_height : float, optional, inches
columns : {1, 2}
"""
# code adapted from http://www.scipy.org/Cookbook/Matplotlib/LaTeX_Examples
# Width and max height in inches for IEEE journals taken from
# computer.org/cms/Computer.org/Journal%20templates/transactions_art_guide.pdf
assert(columns in [1,2])
if fig_width is None:
fig_width = 3.39 if columns==1 else 6.9 # width in inches
if fig_height is None:
golden_mean = (sqrt(5)-1.0)/2.0 # Aesthetic ratio
fig_height = fig_width*golden_mean # height in inches
#MAX_HEIGHT_INCHES = 7.0
#if fig_height > MAX_HEIGHT_INCHES:
# print("WARNING: fig_height too large:" + fig_height +
# "so will reduce to" + MAX_HEIGHT_INCHES + "inches.")
# fig_height = MAX_HEIGHT_INCHES
params = {'backend': 'ps',
'text.latex.preamble': [r'\usepackage{gensymb}'],
'axes.labelsize': 8, # fontsize for x and y labels (was 10)
'axes.titlesize': 8,
'font.size': 8, # was 10
'legend.fontsize': 8, # was 10
'xtick.labelsize': 8,
'ytick.labelsize': 8,
'text.usetex': True,
'figure.figsize': [fig_width,fig_height],
'font.family': 'serif',
'figure.autolayout': True,
'lines.linewidth' : 1.0
}
matplotlib.rcParams.update(params)
def format_axes(ax):
SPINE_COLOR = 'gray'
for spine in ['top', 'right']:
ax.spines[spine].set_visible(False)
for spine in ['left', 'bottom']:
ax.spines[spine].set_color(SPINE_COLOR)
ax.spines[spine].set_linewidth(0.5)
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
for axis in [ax.xaxis, ax.yaxis]:
axis.set_tick_params(direction='out', color=SPINE_COLOR)
#q_sigma = c0 * 22.2 # [nm] hopping fitting parameter
#q_pi = a_cc * 22.2 # [nm] hopping fitting parameter
#r0 = 0.184 * a # [nm] hopping fitting parameter
from mpl_toolkits.axes_grid1 import make_axes_locatable
def getBandstructure(dir1, nPlotBands, EShift):
f = open(dir1+'/generate.bands.dat','r')
print(f)
i = 0
j = 0
l = 0
k = []
E = []
kVec = []
EVec = []
counterPlotBands = 0
for line in f:
i = i+1
a = line.split()
if i==10:
nbands = int(a[5])
print(nbands)
nk = int(a[7])
print(nbands,nk)
if i>16:
if len(a)==0:
j = j+0.5
#print(j)
else:
if (int(j)==int(nbands/2-nPlotBands/2 + counterPlotBands) and int(j) < int(nbands/2+nPlotBands/2)):
if l<nk:
k.append(float(a[0]))
E.append((float(a[1])-EShift))
l = l+1
if l==nk:
kVec.append(k)
EVec.append(E)
l = 0
counterPlotBands += 1
k = []
E = []
return kVec, EVec
def getSingleBand3(dir1, EShift, bandIndex):
f = open(dir1+'/generate.bands.dat','r')
i = 0
j = 0
l = 0
k = []
E = []
kVec = []
EVec = []
counterPlotBands = 0
for line in f:
i = i+1
a = line.split()
if i==10:
nbands = int(a[5])
nk = int(a[7])
#print(nbands,nk)
if i>14:
if len(a)==0:
j = j+0.5
#print(j)
else:
#print(nbands)
if (int(j)==int(nbands/2) + bandIndex):
if l<nk:
k.append(float(a[0]))
E.append(float(a[1])-EShift)
l = l+1
if l==nk:
kVec.append(k)
EVec.append(E)
l = 0
counterPlotBands += 1
k = []
E = []
return kVec, EVec
def getGap(dir1, EShift):
Emin = 10000000
Emax = -10000000
bandIndexVec = [-1]
for bandIndex in bandIndexVec:
kVec, EVec = getSingleBand3(dir1, EShift, bandIndex)
i = 0
if (np.max(EVec)>Emax):
Emax = np.max(EVec)
#if (np.min(EVec)<Emin):
# Emin= np.min(EVec)
bandIndexVec = [0]
for bandIndex in bandIndexVec:
kVec, EVec = getSingleBand3(dir1, EShift, bandIndex)
i = 0
if (np.min(EVec)<Emin):
Emin= np.min(EVec)
gap = (Emin - Emax)*1000
return gap
def getGap2(dir1, EShift):
Emin = 10000000
Emax = -10000000
bandIndexVec = [-3]
for bandIndex in bandIndexVec:
kVec, EVec = getSingleBand3(dir1, EShift, bandIndex)
i = 0
if (np.max(EVec)>Emax):
Emax = np.max(EVec)
#if (np.min(EVec)<Emin):
# Emin= np.min(EVec)
bandIndexVec = [-2]
for bandIndex in bandIndexVec:
kVec, EVec = getSingleBand3(dir1, EShift, bandIndex)
i = 0
if (np.min(EVec)<Emin):
Emin= np.min(EVec)
gap = (Emin - Emax)*1000
return gap
def getEnergyCutPlot(dir1, chosenEnergy, Nx, Ny, cutoffMin, cutoffMax, nEnergy):
os.chdir(dir1)
data = np.genfromtxt("generate.spectral",skip_header=4)
kx = data[:,0]
ky = data[:,1]
kz = data[:,2]
energy = (data[:,3]*3.5)-0.31
spectral = data[:,4]
cutoffMin = cutoff
cutoffMax = cutoff
i = 0
j = 0
eigVec = []
spectralVec = []
eig = np.zeros(nEnergy)
spect = np.zeros(nEnergy)
k = np.zeros(shape=(Nx*Ny,2))
for el1, el2, el3, el4 in zip(kx,ky,energy,spectral):
i = i+1
if (i==1):
k[j,0] = el1
k[j,1] = el2
if (i<=nEnergy):
eig[i-1] = el3
spect[i-1] = el4
if (i==nEnergy):
eigVec.append(eig)
spectralVec.append(spect)
i = 0
j = j+1
eig = np.zeros(nEnergy)
spect = np.zeros(nEnergy)
eigTrueVec = []
for i, kki in enumerate(k):
eigTrue = np.zeros(nEnergy)
eig = eigVec[i]
spec = spectralVec[i]
eigTrue[np.logical_and(np.logical_and(eig>chosenEnergy-cutoffMin,eig<chosenEnergy+cutoffMax),spec>0.0)] = 1.0
specSum = np.sum(spec[np.logical_and(np.logical_and(eig>chosenEnergy-cutoffMin,eig<chosenEnergy+cutoffMax),spec>0.0)])
if (eigTrue.any()==1):
eigTrueVec.append(specSum)
else:
eigTrueVec.append(0)
return k, eigTrueVec
K1 = np.array([1.70276024584813, 0.0000])
K1p = np.array([1.70243417150001, 3.332186294066186E-002])
def getEnergyCutPlot2(dir1, chosenEnergy, Nx, Ny, cutoffMin, cutoffMax, nEnergy):
os.chdir(dir1)
data = np.genfromtxt("generate.spectral")
kx = data[:,0]
ky = data[:,1]
kz = data[:,2]
energy = (data[:,3]*3.5)-0.31
spectral = data[:,4]
cutoffMin = cutoff
cutoffMax = cutoff
i = 0
j = 0
eigVec = []
spectralVec = []
eig = np.zeros(nEnergy)
spect = np.zeros(nEnergy)
k = np.zeros(shape=(Nx*Ny,2))
for el1, el2, el3, el4 in zip(kx,ky,energy,spectral):
i = i+1
if (i==1):
k[j,0] = el1
k[j,1] = el2
if (i<=nEnergy):
eig[i-1] = el3
spect[i-1] = el4
if (i==nEnergy):
eigVec.append(eig)
spectralVec.append(spect)
i = 0
j = j+1
eig = np.zeros(nEnergy)
spect = np.zeros(nEnergy)
eigTrueVec = []
for i, kki in enumerate(k):
eigTrue = np.zeros(nEnergy)
eig = eigVec[i]
spec = spectralVec[i]
eigTrue[np.logical_and(np.logical_and(eig>chosenEnergy-cutoffMin,eig<chosenEnergy+cutoffMax),spec>0.0)] = 1.0
specSum = np.sum(spec[np.logical_and(np.logical_and(eig>chosenEnergy-cutoffMin,eig<chosenEnergy+cutoffMax),spec>0.0)])
if (eigTrue.any()==1):
eigTrueVec.append(specSum)
else:
eigTrueVec.append(0)
return k, eigTrueVec
def getDOS(fileName):
data = np.genfromtxt(fileName)
xdata = data[:,0]
ydata = data[:,1]
return xdata, ydata
K1 = np.array([1.70276024584813, 0.0000])
K1p = np.array([1.70243417150001, 3.332186294066186E-002])
Plot the bandstructure¶
[ ]:
nPlotBands = 40
ncol = 1
nrow = 1
emin = -0.2
emax = 0.2
#emin = -0.002
#emax = 0.007
latexify(columns=1)#, fig_height=1.7)
g1 = gridspec.GridSpec(nrow, ncol)#, height_ratios=[6,1])
g1.update(wspace=0.15, hspace=0.0) # set the spacing between axes.
fig, ((ax0)) = plt.subplots(nrow, ncol, sharex='col', sharey='row')
ax0 = subplot(g1[0])
kpoint = 0.0
gpoint = 0.032230
mpoint = 0.060143
kppoint = 0.076259
factor = kppoint
max1_08 = 0.078838
max1_12 = 0.078838
EShift = 0.302
dir1 = "/Users/nihao/github/moire_course/grabnes2/outputFiles/tBG/"#/useReadXYZ/"
kVec, EVec = getBandstructure(dir1, nPlotBands, EShift)
i = 0
for el1, el2 in zip(kVec,EVec):
i = i+1
if (i==1):
#ax0.plot(el1, el2,color="C1",label=r"KC$_{VV10}$")
ax0.plot(el1, el2,color="C0",label=r"GAP$_{20}$")
else:
ax0.plot(el1, el2,color="C0")
Plot the onsite energies¶
[ ]:
os.chdir("/Users/nihao/github/moire_course/grabnes2/inputFiles/graphene/effectiveGBN/")
data = np.genfromtxt("generate.pos")
xdata = data[:,0][::2]
ydata = data[:,1][::2]
data = np.genfromtxt("generate.e")
zdata = data[:,0][::2]
plt.figure(figsize=(20,10))
plt.scatter(xdata, ydata, c=zdata,cmap="gist_ncar")
for DOS visualization:
os.chdir("/Users/nihao/github/moire_course/grabnes2/outputFiles/graphene/")
xdata, ydata = getDOS("generate.DOS")
plt.plot(xdata,ydata)
[ ]: