In [1]:
import numpy as np
from bokeh.plotting import figure, show
from bokeh.layouts import grid, column, row
from bokeh.io import output_notebook
from bokeh.models import Span, Arrow, VeeHead
output_notebook()
Brillouin zones of the two-dimensional square lattice¶
This notebook demonstrates construction of the first three Brillouin zones of square lattice
In [2]:
# Constructing real space lattice
a1 = np.array([0,2]);
a2 = np.array([2,0]);
N = 3;
x = range(-N, N+1)*np.linalg.norm(a1);
y = range(-N, N+1)*np.linalg.norm(a2);
xg,yg = np.meshgrid(x,y);
In [3]:
# Constructing reciprocal space lattice
b1 = np.array([0,2*np.pi / a1[1]]);
b2 = np.array([2*np.pi / a2[0],0]);
N = 3;
xx = range(-N, N+1)*np.linalg.norm(b1);
yy = range(-N, N+1)*np.linalg.norm(b2);
xxg,yyg = np.meshgrid(xx,yy);
In [4]:
real = figure(title = "Real space lattice", tools = "", x_range = [-10, 10], y_range = [-10, 10], width = 400, height = 400);
real.scatter(xg.flatten(),yg.flatten(),size = 10,fill_color = "blue",line_color = None,line_width = 3);
In [5]:
img = figure(title = "Reciprocal space lattice", tools = "", x_range = [-10, 10], y_range = [-10, 10], width = 400, height = 400);
img.scatter(xxg.flatten(),yyg.flatten(),size = 10,fill_color = "red", line_color = None,line_width = 3);
In [6]:
# plot the real and reciprocal lattice
show(row(real,img))
In [7]:
# draw the reciprocal lattice vectors from the origin to the nearest neighbour
vec1 = img.multi_line([[b1[1], -b1[1]], [0, 0]],[[0, 0], [b2[0], -b2[0]]], line_width = 2, line_color = "black");
arrow1 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=b2[0], y_end=0);
arrow2 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=-b2[0], y_end=0);
arrow3 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=0, y_end=b1[1]);
arrow4 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=0, y_end=-b1[1]);
img.add_layout(arrow1);
img.add_layout(arrow2);
img.add_layout(arrow3);
img.add_layout(arrow4);
show(row(real, img))
2. Draw the Bragg plane bisecting these vectors. Any point on these bisectors will be as close to the origin as it is to the respective nearest reciprocal lattice point.¶
In [8]:
# constructing bragg planes (bisecting the reciprocal vectors drawn in the previous step)
bgp1 = Span(location = b2[0]/2, dimension = "height", line_dash="dashed");
bgp2 = Span(location = -b2[0]/2, dimension = "height", line_dash="dashed");
bgp3 = Span(location = b1[1]/2, dimension = "width", line_dash="dashed");
bgp4 = Span(location = -b1[1]/2, dimension = "width", line_dash="dashed");
bragg1 = img.renderers.extend([bgp1,bgp2,bgp3,bgp4]);
show(row(real, img))
3. Hence the first Brillouin zone will be the area defined by the intersection of these bisectors.¶
In [9]:
# Color the first Brillouin zone, which is the Wigner-Seitz unit cell in the reciprocal lattice
bz1 = img.patch([b2[0]/2, b2[0]/2, -b2[0]/2, -b2[0]/2, b2[0]/2],[b1[1]/2, -b1[1]/2, -b1[1]/2, b1[1]/2, b1[1]/2],line_width = 2, color = "red");
show(row(real,img))
In [10]:
# hide the first brillouin zone elements
vec1.visible = False;
arrow1.visible = False;
arrow2.visible = False;
arrow3.visible = False;
arrow4.visible = False;
bz1.visible = False;
In [11]:
# draw the reciprocal lattice vectors from the origin to the next nearst neighbours
vec2 = img.multi_line([[-b2[0], b2[0]], [-b1[1], b1[1]]],[[b2[0], -b2[0]], [-b1[1], b1[1]]], line_width = 2, line_color = "black");
arrow1 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=b2[0], y_end=b1[1]);
arrow2 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=-b2[0], y_end=-b1[1]);
arrow3 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=-b2[0], y_end=b1[1]);
arrow4 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=b2[0], y_end=-b1[1]);
img.add_layout(arrow1);
img.add_layout(arrow2);
img.add_layout(arrow3);
img.add_layout(arrow4);
show(row(real, img))
In [12]:
# construct bragg planes for the second brillouin zone
bragg2 = img.ray(x = [-b2[0], b2[0], b2[1], b2[1], -b2[0], b2[0], b2[1], b2[1]], y = [b1[0], b1[0], -b1[1], b1[1], b1[0], b1[0], -b1[1], b1[1]], length = 0, angle = [45, -135, 135, -45, -135, 45, -45, 135], angle_units = "deg", color = "black", line_width = 1, line_dash = "dashed");
bragg2.level = "annotation";
show(row(real, img))
In [13]:
# Color both the first and second brillouin zones
bz2 = img.patch([b2[1], b2[0], b2[1], -b2[0], b2[1]],[b1[1], b1[0], -b1[1], b1[0], b1[1]], line_width = 2);
show(row(real, img))
In [14]:
# hide the elements of the first and second brillouin zones
bz2.visible = False;
arrow1.visible = False;
arrow2.visible = False;
arrow3.visible = False;
arrow4.visible = False;
vec2.visible = False;
In [15]:
# draw the reciprocal lattice vectors from the origin to the next next nearst neighbours
vec3 = img.multi_line([[2*b1[1], -2*b1[1]], [0, 0]],[[0, 0], [2*b2[0], -2*b2[0]]], line_width = 2, line_color = "black");
arrow1 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=2*b2[0], y_end=0);
arrow2 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=-2*b2[0], y_end=0);
arrow3 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=0, y_end=2*b1[1]);
arrow4 = Arrow(end = VeeHead(size = 10), x_start=0, y_start=0, x_end=0, y_end=-2*b1[1]);
img.add_layout(arrow1);
img.add_layout(arrow2);
img.add_layout(arrow3);
img.add_layout(arrow4);
show(row(real,img))
In [16]:
# construct bragg planes for the third brillouin zone
bgp1 = Span(location = b2[0], dimension = "height", line_dash="dashed");
bgp2 = Span(location = -b2[0], dimension = "height", line_dash="dashed");
bgp3 = Span(location = b1[1], dimension = "width", line_dash="dashed");
bgp4 = Span(location = -b1[1], dimension = "width", line_dash="dashed");
bragg3 = img.renderers.extend([bgp1,bgp2,bgp3,bgp4]);
show(row(real, img))
Note, however, that the zone is not defined just as an intersection of the newly constructed bisectors. If you check any point in the 4 squares we left out from the intersection, the line connecting the point and the origin goes throw more than 2 Bragg planes. Hence, one must be careful with higher order zones and have all the earlier Bragg planes drawn to decide where the zone lies¶
In [17]:
# color the third (along with the first and second) brillouin zones
bz3 = img.patches([[-b2[0], -b2[0], b2[0], b2[0]],[-b2[0]/2, -b2[0]/2, b2[0]/2, b2[0]/2]], [[-b1[1]/2, b1[1]/2, b1[1]/2, -b1[1]/2], [-b1[1], b1[1], b1[1], -b1[1]]], line_width = 2, color = "indigo");
show(row(real,img))
Show all three Brillouin zones together¶
In [18]:
# overlay all three Brillouin zones along with the bragg planes
bz3.visible = True;
bz3.level = "underlay";
bz2.visible = True;
bz2.level = "glyph";
bz1.visible = True;
bz1.level = "overlay";
vec3.visible = False;
arrow1.visible = False;
arrow2.visible = False;
arrow3.visible = False;
arrow4.visible = False;
show(row(real, img))
Questions¶
- What are the 1st, 2nd, 3rd Brillouin zones of the 1D chain ?
In [ ]:
In [ ]:
In [ ]:
In [ ]: