Kane-Mele Model: 2D TI
See this post for reference.
Hamiltonian given by
\[H = -t_{\mathrm{n}} \sum_{<i\alpha,j\beta>} \left(c^\dagger_{i\alpha} c_{j\beta} + \mathrm{h.c.}\right)
+ it_{\mathrm{so}} \sum_{<<i\alpha,j\beta>>} v_{ij} (S^z)_{\alpha\beta} c^\dagger_{i\alpha} c_{j\beta},\]
where \(v_{ij} = +1\) if \(i\rightarrow j\) is counterclockwise and \(-1\) otherwise.
Imposing zig-zag boundary in the following.
[1]:
import numpy as np
import matplotlib.pyplot as plt
def hamiltonian(k, t_n, t_so, row_count, a):
h0 = hamiltonian_s(k, 0, t_n, t_so, row_count, a)
h1 = hamiltonian_s(k, 1, t_n, t_so, row_count, a)
zero_fill = np.zeros(h0.shape)
return np.block([[h0, zero_fill], [zero_fill, h1]])
# hamiltonian of a fixed spin
def hamiltonian_s(k, s, t_n, t_so, row_count, a):
iak = a * k * 1j
sign_s = (-1) ** s
it_so = t_so * 1j
atom_a = 0
atom_b = 1
atom_count = 2
h = np.zeros((row_count, atom_count, row_count, atom_count), dtype=complex)
h[0, atom_a, 0, atom_b] += t_n
h[0, atom_a, 0, atom_b] += t_n * np.exp(-iak)
h[row_count - 1, atom_a, row_count - 2, atom_a] += it_so * sign_s * np.exp(iak)
h[row_count - 1, atom_a, row_count - 1, atom_a] += it_so * sign_s * np.exp(-iak)
h[row_count - 1, atom_b, row_count - 1, atom_b] += it_so * sign_s * np.exp(iak)
h[row_count - 1, atom_b, row_count - 2, atom_b] += it_so * sign_s
h[0, atom_a, 1, atom_a] += it_so * sign_s
h[0, atom_a, 0, atom_a] += it_so * sign_s * np.exp(-iak)
h[0, atom_b, 0, atom_b] += it_so * sign_s * np.exp(iak)
h[0, atom_b, 1, atom_b] += it_so * sign_s * np.exp(-iak)
for i in range(1, row_count):
h[i, atom_a, i, atom_b] += t_n
h[i, atom_a, i - 1, atom_b] += t_n
h[i, atom_a, i, atom_b] += t_n * np.exp(-iak)
for i in range(1, row_count - 1):
h[i, atom_a, i + 1, atom_a] += it_so * sign_s
h[i, atom_a, i, atom_a] += it_so * sign_s * np.exp(-iak)
h[i, atom_a, i - 1, atom_a] += it_so * sign_s * np.exp(iak)
h[i, atom_b, i - 1, atom_b] += it_so * sign_s
h[i, atom_b, i, atom_b] += it_so * sign_s * np.exp(iak)
h[i, atom_b, i + 1, atom_b] += it_so * sign_s * np.exp(-iak)
h = h.reshape(row_count * atom_count, row_count * atom_count)
return h + h.conj().T
def band_structure(h_k, k_min, k_max, points):
ks = np.linspace(k_min, k_max, points)
eigenvalues = list(map(lambda k: np.linalg.eigvalsh(h_k(k)), ks))
return ks, np.array(eigenvalues)
def plot_band_structure(ks, bands):
bands_count = len(bands[0])
for i in range(bands_count):
plt.plot(ks, bands[:, i])
plt.ylim([-1, 1])
plt.show()
def plot(t_so):
a = 1
t_n = 1
s = 0
row_count = 32
# show band of a single spin only
# h_k = lambda k: hamiltonian_s(k, s, t_n, t_so, row_count, a)
# plot_band_structure(*band_structure(h_k, 0, 2 * np.pi, 500))
h_k_sum = lambda k: hamiltonian(k, t_n, t_so, row_count, a)
plot_band_structure(*band_structure(h_k_sum, 0, 2 * np.pi, 500))
[2]:
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
Drag the slider to see how the gap varies with \(t_{\mathrm{so}}\). Note that the gap closes as \(t_{\mathrm{so}}\rightarrow 0\).
[3]:
interact(plot, t_so=widgets.FloatSlider(
value=0.04,
min=0,
max=0.1,
step=0.01)
);
[ ]: