3D and 2D reciprocal lattice vectors (Python example)

When I started using Density Functional Theory and, even more, when trying to re-create its results in a meaningful piece of material, like a nanoribbon or a nanowire, a lot of the problems came during geometry creation. This is natural, as DFT is a theory to derive quantities like eigenenergies, in a crystal lattice with periodicity. But when trying to switch to a model that is finite in one or more directions, you have to start a sort of mix and match procedure.

During this time (and assuming you are not the one who writes the software), visualizing vectors is maybe the less useful thing to do. Still, there are cases where you need it in order to get a better understanding of things, like visualizing Weyl points.

We know that in the reciprocal lattice, each vector should be orthogonal to the vectors of the direct lattice of all other ‘dimensions’ (axis directions). Therefore, if the direct lattice is not an orthogonal, then it is most probable that the 2D version of the 3D lattice will not be the same.

In this small tutorial I will plot two such sets of vectors, those who correspond to a 2D and those for a 3D hexagonal lattice. Opening any textbook, you will find how to define the reciprocal lattice vectors, b1, b2, b3, in the 3D case,

b_1=\frac{\vec{a_2} \times \vec{a_3}}{V}, b_2=\frac{\vec{a_1} \times \vec{a_3}}{V}, b_3=\frac{\vec{a_1} \times \vec{a_2}}{V}

Where a1, a2 and a3 are the real space vectors and V is the volume of the unit cell,

V = \left(\vec{a_2}\times\vec{a_1}\right)\cdot\vec{a_3}

Note that this last equation is also really useful when dealing with normalized units of conductance.

Putting the two equations together, the equivalent Python code for one of them is simply:

b1_3D = np.cross(a2, a3)/np.dot(a1, np.cross(a2, a3))

And we also need the values for the hexagonal lattice vectors, which we can also easily find in most textbooks and which I will include here as Python input with the lattice constants a,c:

a = 3.19048457e+00
c = 3.24395000e+01
x = np.array([1, 0, 0])
y = np.array([0, 1, 0])
z = np.array([0, 0, 1])
a1=a*x
a2 = ((a/2) * x) + ((np.cbrt(3)/2) * a * y)
a3 = c * z
Real and reciprocal lattice vectors of the 3D hexagonal lattice

We can clearly see (at least for the xy plane) that b1 is perpendicular to a2 and b2 to a1. You can do the calculation by yourself, and you can check that the two vectors have zero z components.

Knowing all this, the calculation of the 2D reciprocal vectors almost feels like cheating. We take advantage of this last property of vectors being perpendicular to the reciprocal of the other and use a rotation vector to help us,

R=\begin{pmatrix}\cos\theta&-\sin\theta\\ \sin\theta&\cos\theta\end{pmatrix}

The precise equations are,

b_1 = 2\pi\frac{Ra_2}{a_1\cdot Ra_2} b_2 = 2\pi\frac{Ra_1}{a_2\cdot Ra_1}

Real and reciprocal lattice vectors of the 2D hexagonal lattice

As before, the vectors are correctly perpendicular, but the reciprocal vectors are now more ‘spread out’ in space. The question now becomes… Will we get the same result if, instead of using the 2D formula, we use the 3D formula and truncate out the components in the third dimension? Can you think of a case where the two will give us the same results?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s