Plotting honeycomb crystal lattice

147 views
Skip to first unread message

saad khalid

unread,
May 16, 2019, 11:35:54 PM5/16/19
to sage-support
Hi everyone:

I'm trying to using Sage's plot functionality to plot the honeycomb lattice:

Plotting the honeycomb lattice is slightly different from plotting a simple (like a square) lattice, as each site is technically two points, with a basis vector pointing from one point to the other within a single site. So you take your two lattice vectors and start from some point and generate all possible points from those lattice vectors. Then you go back to your starting point, shift by the basis vector, and then generate all possible points from there using the lattice vector, and then you add these two sets of points together to get the honeycomb lattice. I've figured out how to do it using points at the corner of each hexagon, like this:
list_plot(flatten([[a*vector([sqrt(3)/2,1/2]) + b*vector([sqrt(3)/2,-1/2]) for a in (0..30)] for b in (0..30)] + [[a*vector([sqrt(3)/2,1/2]) + b*vector([sqrt(3)/2,-1/2]) + vector([-1/sqrt(2),0]) for a in (0..30)] for b in (0..30)]))

However, I was hoping to do this with lines outlining the hexagons as shown in the linked image. Would anyone know of a way to do this? Thanks!

Grumby

unread,
May 18, 2019, 2:44:15 PM5/18/19
to sage-support

Grumby

unread,
May 18, 2019, 2:46:48 PM5/18/19
to sage-support
Hello,

You have to draw lines between your points.
A solution is to use polyhedron. For instance :

hexa0 = polytopes.regular_polygon(6)
hexa1 = hexa0.translation([float(sqrt(3))/2,1.5])

g = Graphics()

i = 0
while i < 6:
    j = 0
    while j < 4:       
        hexa00 = hexa0.translation([i*float(sqrt(3)),j*(3)])
        outline00 = hexa00.projection().render_outline_2d()
        hexa11 = hexa1.translation([i*float(sqrt(3)),j*(3)])
        outline11 = hexa11.projection().render_outline_2d()
   
        g += outline00 + outline11
       
        j += 1
    i += 1
   
g.show(aspect_ratio=1)

Grumby

unread,
May 18, 2019, 6:20:59 PM5/18/19
to sage-support
To draw lines between points P1 and P2 you can use line ([(x1, y1), (x2, y2)]). But to know which point P1 to join to which point P2 you must:
Either build your points in a logical way to have a method to join them.
Or calculate the distances between all your points (900 points! 900*899/2 distances ?) ?) And keep only the points whose distance is equal to 1 (in approximate value of course). Which is frankly long even if you have a fast computer.
That's why I suggested you go through Polyedron.

Grumby

unread,
May 19, 2019, 6:30:10 AM5/19/19
to sage-support
You can try this to draw the lines between the different points. 
The difficulty is to select in your array the points that match together.


import numpy as np
n = 30

array = flatten([[a*vector([float(sqrt(3))/2,0.5]) + b*vector([float(sqrt(3))/2,-0.5]) for a in (0..n)] for b in (0..n)] + [[a*vector([float(sqrt(3))/2,0.5]) + b*vector([float(sqrt(3))/2,-0.5]) + vector([-1/float(sqrt(2)),0]) for a in (0..n)] for b in (0..n)])
arrayP = np.asarray(array)

g = Graphics()
i = 0
while i < n**2:
    pointO = arrayP[i]
    pointA = arrayP[i + (n+1)**2]
    pointB = arrayP[i + (n+1)**2 +1]
    pointC = arrayP[i + (n+1)**2 + n+1]
    
    line1 = line([pointO,pointA],aspect_ratio=1)
    line2 = line([pointO,pointB],aspect_ratio=1)
    line3 = line([pointO,pointC],aspect_ratio=1)
 
 
    if i%(n+1) == n:    #to avoid long return lines between points   
        g += line1 + line3
    else:  
        g += line1 + line2 +line3
    
    i +=1
g


Le vendredi 17 mai 2019 05:35:54 UTC+2, saad khalid a écrit :
Reply all
Reply to author
Forward
0 new messages