File size: 1,692 Bytes
1c703f0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import numpy as np


def ChangeBasis(r, target, ref=np.eye(2)):
    """ Changes the basis of the r vectors from A to B.

      The matrices A and B contain the basis elements in a common basis.
      The vectors r are assumend in the basis A basis, i.e:

      $\vec{r}_i = \alpha_1 \vec{a}_1 + \alpha_2 \vec{a}_2$

      The goal is to found the coefficients $(\beta_1,\beta_2)$, such that

      $\vec{r}_i = \beta_1 \vec{b}_1 + \beta_2 \vec{b}_2$.

      By taking the dot product of $\vec{r}_i$ agains $\vec{b}_j$, we found
      the following system of equations

      $\vec{b}_i\cdot\vec{b}_j \beta_i = \vec{b}_i\cdot\vec{a}_j \alpha_j$.

      Therefore, the matrix $U_{ij} = \vec{b}_i\cdot\vec{a}_j$ is the change of
      basis matrix
  """
    A, B = ref, target
    r = np.array(r)
    U = np.linalg.inv(B.T @ B).dot(B.T @ A)
    return U @ r


def supercell_points(dims, lat_vec, fractional=False):
    """
    A gird of points in the corners of the lattice vectors
    :param dims:
    :param lat_vec:
    :param fractional:
    :return:
    """
    nx, ny = dims;
    grid = np.mgrid[-nx:nx, -ny:ny].T.reshape(nx * 2 * ny * 2, 2).T
    if fractional:
        return grid
    return lat_vec @ grid


def get_supercell_vectors(dims, ref, target, tol=1e-2):
    """
    Received a set of points x in the reference lattice basis and returns those
    that are close to the reference lattice points given a tolerance tol.
    """
    B, A = ref, target
    Bpoints = supercell_points(dims, B)  # This points are in cartesians
    rBinA = ChangeBasis(Bpoints, A)  # Map from cartesian to Alat coordinates

    return Bpoints[:, np.linalg.norm(np.round(rBinA) - rBinA, axis=0) < tol]