translation-vectors
$\mathbf{a}_0 = (1, )$
$\mathbf{b}_0 = (2\pi, )$
translation-vectors
$\mathbf{a}_1 = (0, 1)$
$\mathbf{b}_0 = (2\pi, 0)$
translation-vectors
$\mathbf{a}_1 = (\frac{1}{2}, \frac{\sqrt{3}}{2})$
$\mathbf{b}_0 = (2\pi, -\frac{2\pi}{\sqrt{3}})$
translation-vectors
$\mathbf{a}_1 = (\frac{1}{2}, \frac{\sqrt{3}}{2})$
$\mathbf{b}_0 = (2\pi, -\frac{2\pi}{\sqrt{3}})$
translation-vectors
$\mathbf{a}_1 = (\frac{1}{2}, \frac{\sqrt{3}}{2})$
$\mathbf{b}_0 = (2\pi, -\frac{2\pi}{\sqrt{3}})$
translation-vectors
$\mathbf{a}_2 = (0, 0, 1)$
$\mathbf{b}_0 = (2\pi, 0, 0)$
translation-vectors
$\mathbf{a}_1 = (3, -2)$
$\mathbf{b}_0 = (\frac{\pi}{3}, \frac{\pi}{2})$
translation-vectors
$\mathbf{a}_1 = (1, -3)$
$\mathbf{b}_0 = (\frac{3\pi}{5}, \frac{\pi}{5})$
translation-vectors
$\mathbf{a}_1 = (\frac{5}{2}, -\frac{3\sqrt{3}}{2})$
$\mathbf{b}_0 = (\frac{6\pi}{13}, \frac{10\pi}{13\sqrt{3}})$
translation-vectors
$\mathbf{a}_1 = (\frac{3}{2}, -\frac{\sqrt{3}}{2})$
$\mathbf{b}_0 = (\frac{2\pi}{3}, \frac{2\pi}{\sqrt{3}})$
translation-vectors
$\mathbf{a}_1 = (\frac{5}{2}, -\frac{\sqrt{3}}{2})$
$\mathbf{b}_0 = (\frac{2\pi}{5}, \frac{2\pi}{\sqrt{3}})$
translation-vectors
$\mathbf{a}_1 = (3, -\sqrt{3})$
$\mathbf{b}_0 = (\frac{\pi}{3}, \frac{\pi}{\sqrt{3}})$
In [1]:
from itertools import product
import matplotlib.pyplot as plt
import numpy as np
In [2]:
# database for some commonly used unit-cells
dtype = np.float64
chain_cell_info = {
"points": np.array([[0.0]], dtype=dtype),
"vectors": np.array([[1.0]], dtype=dtype)
}
square_cell_info = {
"points": np.array([[0.0, 0.0]], dtype=dtype),
"vectors": np.array([[1.0, 0.0], [0.0, 1.0]], dtype=dtype)
}
triangle_cell_info = {
"points": np.array([[0.0, 0.0]], dtype=dtype),
"vectors": np.array([[1.0, 0.0], [0.5, np.sqrt(3)/2]], dtype=dtype)
}
honeycomb_cell_info = {
"points": np.array([[0.0, 0.0], [0.0, 1/np.sqrt(3)]], dtype=dtype),
"vectors": np.array([[1.0, 0.0], [0.5, np.sqrt(3)/2]], dtype=dtype)
}
kagome_cell_info = {
"points": np.array(
[[0, 0], [0.25, np.sqrt(3)/4], [0.5, 0.0]], dtype=dtype
),
"vectors": np.array([[1, 0], [0.5, np.sqrt(3)/2]], dtype=dtype)
}
cubic_cell_info = {
"points": np.array([[0.0, 0.0, 0.0]], dtype=dtype),
"vectors": np.array(
[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]], dtype=dtype
)
}
common_cells_info = {
"chain": chain_cell_info,
"square": square_cell_info,
"triangle": triangle_cell_info,
"honeycomb": honeycomb_cell_info,
"kagome": kagome_cell_info,
"cubic": cubic_cell_info,
}
In [3]:
# database for some commonly used clusters
square_cross_info = {
"points": np.array(
[[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 2.0],
[2.0, 2.0], [2.0, 1.0], [3.0, 1.0], [3.0, 0.0],
[2.0, 0.0], [2.0, -1.0], [1.0, -1.0], [1.0, 0.0]],
dtype=dtype
),
"vectors": np.array([[3.0, 2.0], [3.0, -2.0]], dtype=dtype)
}
square_z_info = {
"points": np.array(
[[0.0, 0.0], [0.0, 1.0], [0.0, 2.0], [1.0, 2.0], [1.0, 3.0],
[2.0, 3.0], [2.0, 2.0], [2.0, 1.0], [1.0, 1.0], [1.0, 0.0]],
dtype=dtype
),
"vectors": np.array([[3.0, 1.0], [1.0, -3.0]], dtype=dtype)
}
triangle_star_info = {
"points": np.array(
[[0.0, 0.0],
[0.0, -np.sqrt(3)], [-0.5, -np.sqrt(3)/2], [-1.5, -np.sqrt(3)/2],
[-1.0, 0.0], [-1.5, np.sqrt(3)/2], [-0.5, np.sqrt(3)/2],
[0.0, np.sqrt(3)], [0.5, np.sqrt(3)/2], [1.5, np.sqrt(3)/2],
[1.0, 0.0], [1.5, -np.sqrt(3)/2], [0.5, -np.sqrt(3)/2]],
dtype=dtype
),
"vectors": np.array(
[[3.5, np.sqrt(3)/2], [2.5, -1.5*np.sqrt(3)]], dtype=dtype
)
}
honeycomb_benzene_info = {
"points": np.array(
[[0.0, 0.0], [0.0, 1/np.sqrt(3)], [0.5, np.sqrt(3)/2],
[1.0, 1/np.sqrt(3)], [1.0, 0.0], [0.5, -0.5/np.sqrt(3)]],
dtype=dtype
),
"vectors": np.array(
[[1.5, np.sqrt(3)/2], [1.5, -np.sqrt(3)/2]], dtype=dtype
)
}
honeycomb_diphenyl_info = {
"points": np.array(
[[0.0, 0.0], [0.0, 1/np.sqrt(3)], [0.5, np.sqrt(3)/2],
[1.0, 1/np.sqrt(3)], [1.5, np.sqrt(3)/2], [2.0, 1/np.sqrt(3)],
[2.0, 0.0], [1.5, -0.5/np.sqrt(3)], [1.0, 0.0],
[0.5, -0.5/np.sqrt(3)]],
dtype=dtype
),
"vectors": np.array(
[[2.5, np.sqrt(3)/2], [2.5, -np.sqrt(3)/2]], dtype=dtype
)
}
honeycomb_gear_info = {
"points": np.array(
[[0.0, 0.0], [0.0, 1/np.sqrt(3)], [0.5, np.sqrt(3)/2],
[0.5, 2.5/np.sqrt(3)], [1.0, np.sqrt(3)], [1.5, 2.5/np.sqrt(3)],
[2.0, np.sqrt(3)], [2.5, 2.5/np.sqrt(3)], [2.5, np.sqrt(3)/2],
[3.0, 1/np.sqrt(3)], [3.0, 0.0], [2.5, -0.5/np.sqrt(3)],
[2.5, -np.sqrt(3)/2], [2.0, -2/np.sqrt(3)], [1.5, -np.sqrt(3)/2],
[1.0, -2/np.sqrt(3)], [0.5, -np.sqrt(3)/2], [0.5, -0.5/np.sqrt(3)],
[1.0, 0.0], [1.0, 1/np.sqrt(3)], [1.5, np.sqrt(3)/2],
[2.0, 1/np.sqrt(3)], [2.0, 0.0], [1.5, -0.5/np.sqrt(3)]],
dtype=dtype
),
"vectors": np.array([[3, np.sqrt(3)], [3, -np.sqrt(3)]], dtype=dtype)
}
special_clusters_info = {
"square_cross": square_cross_info,
"square_12": square_cross_info,
"cross": square_cross_info,
"square_z": square_z_info,
"square_10": square_z_info,
"z": square_z_info,
"triangle_star": triangle_star_info,
"triangle_13": triangle_star_info,
"star": triangle_star_info,
"honeycomb_benzene": honeycomb_benzene_info,
"honeycomb_6": honeycomb_benzene_info,
"benzene": honeycomb_benzene_info,
"honeycomb_diphenyl": honeycomb_diphenyl_info,
"honeycomb_10": honeycomb_diphenyl_info,
"diphenyl": honeycomb_diphenyl_info,
"honeycomb_gear": honeycomb_gear_info,
"honeycomb_24": honeycomb_gear_info,
"gear": honeycomb_gear_info,
}
In [4]:
def special_cluster(which):
"""
Generating some special cluster
Parameters
----------
which : str
Which special lattice to generate
Currently supported special lattice:
"square_cross" | "square_z" | "triangle_star" |
"honeycomb_benzene" | "honeycomb_diphenyl" | "honeycomb_gear"
Alias:
"square_cross" | "square_12" | "cross";
"square_z" | "square_10" | "z";
"triangle_star" | "triangle_13" | "star";
"honeycomb_benzene" | "honeycomb_6"| "benzene";
"honeycomb_diphenyl" | "honeycomb_10" | "diphenyl";
"honeycomb_gear" | "honeycomb_24" | "gear"
Returns
-------
points : ndarray
The coordinates of the points in the cluster
vectors : ndarray
The translation vectors of the cluster
"""
try:
cluster_info = special_clusters_info[which]
return cluster_info["points"], cluster_info["vectors"]
except KeyError:
raise KeyError("Unrecognized special lattice name!")
def lattice_generator(which, num0=1, num1=1, num2=1):
"""
Generating a common cluster with translation symmetry
Parameters
----------
which : str
Which type of lattice to generate.
Legal value:
"chain" | "square" | "triangle" | "honeycomb" | "kagome" | "cubic"
num0 : int, optional
The number of unit cell along the first translation vector
default: 1
num1 : int, optional
The number of unit cell along the second translation vector. It only
takes effect for 2D and 3D lattice.
default: 1
num2 : int, optional
The number of unit cell along the second translation vector. It only
takes effect for 3D lattice.
default : 1
Returns
-------
points : ndarray
The coordinates of the points in the cluster
vectors : ndarray
The translation vectors of the cluster
"""
assert isinstance(num0, int) and num0 >= 1
assert isinstance(num1, int) and num1 >= 1
assert isinstance(num2, int) and num2 >= 1
try:
cell_info = common_cells_info[which]
cell_points = cell_info["points"]
cell_vectors = cell_info["vectors"]
except KeyError:
raise KeyError("Unrecognized lattice type!")
if which == "chain":
if num0 == 1:
return cell_points, cell_vectors
else:
vectors = cell_vectors * np.array([[num0]])
mesh = product(range(num0))
elif which == "cubic":
if num0 == 1 and num1 == 1 and num2 == 1:
return cell_points, cell_vectors
else:
vectors = cell_vectors * np.array([[num0], [num1], [num2]])
mesh = product(range(num0), range(num1), range(num2))
else:
if num0 == 1 and num1 == 1:
return cell_points, cell_vectors
else:
vectors = cell_vectors * np.array([[num0], [num1]])
mesh = product(range(num0), range(num1))
dim = cell_points.shape[1]
dRs = np.matmul(list(mesh), cell_vectors)
points = np.reshape(dRs[:, np.newaxis, :] + cell_points, newshape=(-1, dim))
return points, vectors
def show(points, vectors, scope=0):
"""
Plot the given `points`
Parameter
---------
points : ndarray
The coordinates of the points
vectors : ndarray
The trnaslation vectors of the cluster
scope : int, optional
Determine the number of cluster to draw
default: 0
"""
assert isinstance(points, np.ndarray) and points.ndim == 2
assert isinstance(vectors, np.ndarray) and vectors.ndim == 2
assert isinstance(scope, int) and scope >= 0
point_num, space_dim = points.shape
trans_dim, tmp = vectors.shape
if space_dim > 2:
raise ValueError("Not supported space dimension!")
if trans_dim > space_dim:
raise ValueError("The number of translation vectors should be no more than the space dimension!")
if tmp != space_dim:
raise ValueError("The translation vectors should have the same space dimension as the points!")
clusters = [
points + np.matmul(tmp, vectors)
for tmp in product(range(-scope, scope+1), repeat=trans_dim)
]
fig, ax = plt.subplots()
fig.set_size_inches((16, 9))
ax.set_axis_off()
ax.set_aspect("equal")
if space_dim == 1:
ys = np.zeros(shape=points.shape)
for cluster in clusters:
ax.plot(cluster, ys, marker="o", ls="None", ms=8)
else:
for cluster in clusters:
ax.plot(cluster[:, 0], cluster[:, 1], marker="o", ls="None", ms=8)
left, right = ax.get_xlim()
bottom, top = ax.get_ylim()
half = max(right - left, top - bottom) / 2
x_center = (right + left) / 2
y_center = (top + bottom) / 2
ax.set_xlim(left=x_center-half, right=x_center+half)
ax.set_ylim(bottom=y_center-half, top=y_center+half)
plt.show()
In [5]:
show(*special_cluster("square_cross"), scope=1)
In [6]:
show(*special_cluster("square_z"), scope=1)
In [7]:
show(*special_cluster("triangle_star"), scope=1)
In [8]:
show(*special_cluster("honeycomb_benzene"), scope=1)
In [9]:
show(*special_cluster("honeycomb_diphenyl"), scope=1)
In [10]:
show(*special_cluster("honeycomb_gear"), scope=1)
In [11]:
num = 4
show(*lattice_generator("chain", num0=num), scope=1)
In [12]:
show(*lattice_generator("square", num0=num, num1=num), scope=1)
In [13]:
show(*lattice_generator("triangle", num0=num, num1=num), scope=1)
In [14]:
show(*lattice_generator("honeycomb", num0=num, num1=num), scope=1)
In [15]:
show(*lattice_generator("kagome", num0=num, num1=num), scope=1)