Esempio n. 1
0
 def get_integer(vec):
     # Used vec = np.array(vec, dtype=float) before, but does not work for
     # [5.00000000e-01, -5.00000000e-01,  2.22044605e-16] in Sigma3[112]
     vec = np.round(vec, 12)
     vec_sign = np.array([1 if abs(i) == i else -1 for i in vec])
     vec = list(abs(vec))
     new_vec = []
     if 0.0 in vec:
         zero_ind = vec.index(0)
         vec.pop(zero_ind)
         if 0.0 in vec:
             new_vec = [get_smallest_multiplier(vec) * i for i in vec]
         else:
             frac = Fraction(vec[0] / vec[1]).limit_denominator()
             new_vec = [frac.numerator, frac.denominator]
         new_vec.insert(zero_ind, 0)
     else:
         for i in range(len(vec) - 1):
             frac = Fraction(vec[i] / vec[i + 1]).limit_denominator()
             new_vec.extend([frac.numerator, frac.denominator])
         if new_vec[1] == new_vec[2]:
             new_vec = [new_vec[0], new_vec[1], new_vec[3]]
         else:
             new_vec = reduce_vector([new_vec[0] * new_vec[2],
                                      new_vec[1] * new_vec[2],
                                      new_vec[3] * new_vec[1]])
     assert is_integer(new_vec)
     return new_vec * vec_sign
Esempio n. 2
0
def orthogonalize_csl(csl, axis):
    """
    (1) Set the 3rd column of csl same as the rotation axis. The algorithm was
    borrowed from gosam project with slight changes. Link to the project:
    https://github.com/wojdyr/gosam
    (2) Orthogonalize CSL, which is essentially a Gram-Schmidt process. At the
    same time, we want to make sure the column vectors of orthogonalized csl
    has the smallest value possible. That's why we compared two different ways.
    csl = [v1, v2, v3], vi is the column vector
    u1 = v3/||v3||, y2 = v1 - (v1 . u1)u1
    u2 = y2/||y2||, y3 = v3 - [(v3 . u1)u1 + (v3 . u2)u2]
    u3 = y3/||y3||
    """
    axis = np.array(axis)
    c = solve(csl.transpose(), axis)
    if not is_integer(c):
        mult = get_smallest_multiplier(c)
        c *= mult
    c = c.round().astype(int)
    ind = min([(i, v) for i, v in enumerate(c) if not np.allclose(v, 0)],
              key=lambda x: abs(x[1]))[0]
    if ind != 2:
        csl[ind], csl[2] = csl[2].copy(), -csl[ind]
        c[ind], c[2] = c[2], -c[ind]

    csl[2] = np.dot(c, csl)
    if c[2] < 0:
        csl[1] *= -1

    def get_integer(vec):
        # Used vec = np.array(vec, dtype=float) before, but does not work for
        # [5.00000000e-01, -5.00000000e-01,  2.22044605e-16] in Sigma3[112]
        vec = np.round(vec, 12)
        vec_sign = np.array([1 if abs(i) == i else -1 for i in vec])
        vec = list(abs(vec))
        new_vec = []
        if 0.0 in vec:
            zero_ind = vec.index(0)
            vec.pop(zero_ind)
            if 0.0 in vec:
                new_vec = [get_smallest_multiplier(vec) * i for i in vec]
            else:
                frac = Fraction(vec[0] / vec[1]).limit_denominator()
                new_vec = [frac.numerator, frac.denominator]
            new_vec.insert(zero_ind, 0)
        else:
            for i in range(len(vec) - 1):
                frac = Fraction(vec[i] / vec[i + 1]).limit_denominator()
                new_vec.extend([frac.numerator, frac.denominator])
            if new_vec[1] == new_vec[2]:
                new_vec = [new_vec[0], new_vec[1], new_vec[3]]
            else:
                new_vec = reduce_vector([new_vec[0] * new_vec[2],
                                         new_vec[1] * new_vec[2],
                                         new_vec[3] * new_vec[1]])
        assert is_integer(new_vec)
        return new_vec * vec_sign

    u1 = csl[2] / norm(csl[2])
    y2_1 = csl[1] - np.dot(csl[1], u1) * u1
    c0_1 = get_integer(y2_1)
    y2_2 = csl[0] - np.dot(csl[0], u1) * u1
    c0_2 = get_integer(y2_2)
    if sum(abs(c0_1)) > sum(abs(c0_2)):
        u2 = y2_2 / norm(y2_2)
        y3 = csl[1] - np.dot(csl[1], u1) * u1 - np.dot(csl[1], u2) * u2
        csl[1] = get_integer(y3)
        csl[0] = c0_2
    else:
        u2 = y2_1 / norm(y2_1)
        y3 = csl[0] - np.dot(csl[0], u1) * u1 - np.dot(csl[0], u2) * u2
        csl[1] = c0_1
        csl[0] = get_integer(y3)
    for i in range(3):
        for j in range(i + 1, 3):
            if not np.allclose(np.dot(csl[i], csl[j]), 0):
                raise ValueError("Non-orthogonal basis: %s" % csl)
    return csl.round().astype(int)