A Moiré pattern is an interference pattern that occurs when two grids of repeating lines or shapes are rotated by a small amount relative to one another (oblig. xkcd).
A recent application concerned the experimental verification of Hofstadter's butterfly: Douglas Hofstadter (he of Gödel, Escher, Bach fame) predicted in a 1976 paper that the energy structure of the electrons in a twodimensional lattice of atoms in a magnetic field has a fractal structure. The problem with the experimental verification of this prediction is that the lattice dimensions of a typical solid material are so small that it would be unfeasible to generate the necessary magnetic field to make the energy structure measurable.
In 2013, three research groups were able to verify the claim by placing a layer of graphene on a substrate layer of boron nitride (which has a very similar hexagonal atomic structure), at such an angle that the resulting Moiré pattern had a much larger repeating length scale.
The code below generates an SVG image of two hexagonal lattices, rotated by a specified amount, which shows the repeating Moiré pattern that results.
import numpy as np
# Image dimensions and grid lattice size, a.
width, height = 600, 400
a = 5
# a.sin(60) and a.cos(60)
gx, gy = a * np.sqrt(3)/2, a/2
# The number of unit cells, horizontally and vertically.
nx, ny = int(width / 2 / gx)+1, int(height / (a + gy))+1
# We'll need the coordinates of the centre of the image when we come to rotate.
cx, cy = width / 2, height / 2
def svg_line(x0, y0, x1, y1, th=0, cls=None):
"""Return the SVG for a single, line possibly rotated by th radians."""
def rotate(x, y, th):
"""Rotate the coordinates (x,y) about the centre (cx,cy)."""
c, s = np.cos(th), np.sin(th)
xp, yp = xcx, ycy
x, y = c*xp  s*yp, s*xp + c*yp
return x+cx, y+cy
if th != 0:
x0, y0 = rotate(x0, y0, th)
x1, y1 = rotate(x1, y1, th)
# If an SVG class has been provided, add it to the line element.
s_cls = 'class="{}"'.format(cls) if cls else ''
return '<line x1="{}" y1="{}" x2="{}" y2="{}" {}/>'.format(
x0, y0, x1, y1, s_cls)
def add_unit_cell(s, x0, y0, th=0, cls=None):
"""Add a unit cell from the lattice to the SVG output.
The "unit cell" consists of the arrangement of lines: \ /

centred at the vertex where they meet. th is the angle of rotation, in
radians and cls is an optional SVG class to add to the <line> element.
"""
s.append(svg_line(x0, y0, x0, y0+a, th, cls))
s.append(svg_line(x0, y0, x0gx, y0gy, th, cls))
s.append(svg_line(x0, y0, x0+gx, y0gy, th, cls))
def svg_preamble(s):
"""The usual SVG preamble and style definitions."""
s.append('<?xml version="1.0" encoding="utf8"?>')
s.append('<svg xmlns="http://www.w3.org/2000/svg"\n' + ' '*5 +
'xmlns:xlink="http://www.w3.org/1999/xlink" width="{}" height="{}" >'
.format(width, height))
s.append("""<defs>
<style type="text/css"><![CDATA[
line {
strokewidth: 2px;
stroke: #000;
}
.lattice1 {
stroke: #824e4e;
}
.lattice2 {
stroke: #4a5f70;
}
>]]></style>
</defs>
""")
s = []
svg_preamble(s)
# Angle of rotation of the lattices (degrees)
th = 10
# An internal variable to offset every other row of the unit cells when drawing
_ph = 0
for iy in range(ny):
_ph = 0 if _ph else gx
for ix in range(nx):
add_unit_cell(s, ix*2*gx + _ph, iy*(a+gy), cls='lattice1')
add_unit_cell(s, ix*2*gx + _ph, iy*(a+gy), np.radians(th), 'lattice2')
s.append('</svg>')
with open('lattice.svg', 'w') as fo:
print('\n'.join(s), file=fo)
Comments
Comments are premoderated. Please be patient and your comment will appear soon.
Alfonsi Jessica 3 years, 10 months ago
Wonderful blog! It makes Python even more appealing to me, I just need a good problem to start learning by coding.
Link  ReplyHave a look at my Mathematica Demonstration I published 5 years ago
http://demonstrations.wolfram.com/MoirePatternsAndCommensurabilityInRotatedGrapheneBilayers/
christian 3 years, 10 months ago
Thank you! I think we may have been reading the same papers about rotated graphene layers. I was going to write something about Hofstadter's Butterfly as well but never got round to it...
Link  ReplyAlfonsi Jessica 3 years, 10 months ago
I have been thinking often about plotting Hofstadter's butterfly for different lattices, square and hexagonal, but now I'm looking into other systems. There's a recent IOP ebook https://iopscience.iop.org/book/9781681741178
Link  ReplyVishal Kumar 3 years, 5 months ago
Is it possible to get an animation of changing angles? That will be really good.
Link  ReplyRODOLFO 3 years, 5 months ago
LOS INVITO A VER ESTO QUE SUBI HACE 8 AÑOS A YOUTUBECUANDO AUN NO SE HABLABA DE ANGULO MAGICO.
Link  ReplyY NO TIENEN IDEA DE LO QUE ESCONDE ESTE PATRÓN.
https://youtu.be/2lYp1uDG_ic
Yitzhak Weissman 2 years, 9 months ago
I am presently investigating the Moire effect in three dimensions, using Python. This Blog is a true goldmine for me. Thank you, Christian.
Link  Replychristian 2 years, 9 months ago
Thank you for your comment – glad you're finding it interesting!
Link  ReplyNew Comment