Beispiel #1
0
def csl_finder_smith(r_g1tog2_g1):
    """
    This funciton extracts the CSL basis when transformation between the two
    lattices is given (r_g1tog2_g1). The algorithms used are based on the
    following article: doi:10.1107/S056773947601231X)

    Parameters
    ----------------
    r_g1tog2_g1: numpy array
    The 3x3 transformation matrix in g1 reference frame

    Returns
    -----------
    l_csl_g1: numpy array
    3 x 3 matrix with the csl basis vectors as columns

    Notes
    ---------
    The "Reduced" refer to the use of LLL algorithm to compute a
    basis that is as close to orthogonal as possible.
    (Refer to http://en.wikipedia.org/wiki/Lattice_reduction) for further
    detials on the concept of Lattice Reduction
    """
    R_G1ToG2_G1 = np.array(r_g1tog2_g1)
    L_G2_G1 = R_G1ToG2_G1

    # Obtain N1 and N2
    N1, _ = int_man.int_mult(L_G2_G1)
    A = np.dot(N1, L_G2_G1)

    # Check that A is an integer matrix
    if int_man.int_check(A, 12).all():
        A = np.around(A)
    else:
        raise Exception('L_G2_G1 is not a Sigma Transformation')
    # Smith Normal Form of A
    # A = U*E*V'
    U, E, _ = smith_nf(A)
    L_G1n_G1 = U
    # L_G1_G1n = np.linalg.inv(L_G1n_G1)

    # CSL Bases
    l_csl_g1 = csl_elem_div_thm_l1(E / N1, L_G1n_G1)

    if(int_man.int_check(l_csl_g1, 1e-08)).all():
        l_csl_g1 = np.around(l_csl_g1)
    else:
        raise Exception('l_csl_g1 is not defined in L_G1_G1 axis')

    # Reduced CSL bases using the LLL algorithm
    l_csl_g1 = lll_reduction((l_csl_g1))
    return l_csl_g1
Beispiel #2
0
def test_int_check():
    """
    Test cases for the int_check function in integer_manipulations
    """
    b = np.array([[2, 3, 5], [6, 6.000002, -2.000001], [-0.00002, 1.5, 4]])
    a = int_man.int_check(b)
    print(a)
    # ------------
    b = 2.5
    a = int_man.int_check(b)
    print(a)
    if __name__ == '__main__':
        test_int_check
Beispiel #3
0
def csl_finder_2d(l_pl1_g1, l_pl2_g1):
    """
    Given two plane bases, the 2D CSL bases are obtined by utilizing the
    smith normal form of the transformation between the two bases

    Parameters
    ---------------
    l_pl1_g1, l_pl2_g1: numpy array
    Basis vectors of planes 1 and 2 expressed in g1 reference frame

    Returns
    ---------------
    l_2d_csl_g1: numpy array
    The basis vectors of the 2D CSL expressed in g1 reference frame
    """

    l1 = np.array(l_pl1_g1)
    l2 = np.array(l_pl2_g1)

    # L2 = L1*T (T := T_Pl1ToPl2_Pl1)
    l1_linv = np.dot(np.linalg.inv(np.dot(l1.T, l1)), l1.T)
    t = np.dot(l1_linv, l2)

    # # Obtain N1 and N2
    n1, a = int_man.int_mult(t)

    if int_man.int_check(a, 12).all:
        a = np.around(a)

    # A = U*E*V'; E is a diagonal matrix
    u, e, v = smith_nf(a)

    l2_n = np.dot(l2, np.linalg.inv(v.T))
    l_2d_csl_g1 = fcd.csl_elem_div_thm_l2(e/n1, l2_n)

    if int_man.int_check(l_2d_csl_g1, 10).all():
        l_2d_csl_g1 = np.around(l_2d_csl_g1)
    else:
        raise Exception('Wrong CSL computation')

    l_2d_csl_g1 = lll_reduction(l_2d_csl_g1[:, 0:2])

    return l_2d_csl_g1
Beispiel #4
0
def check_int_mats(l1, l2):
    """
    The function checks whether or not the elements of
    $A_{left}^{-1}$*B are integers

    Parameters
    ----------
    l1, l2 : numpy arrays of same dimensions

    Returns
    -------
    cond: numpy boolean array
    """

    l1_linv = np.dot(np.linalg.inv(np.dot(l1.T, l1)), l1.T)
    cond = int_man.int_check(np.dot(l1_linv, l2), 10)
    return cond
Beispiel #5
0
def message_display(CheckMatrix, Checknumber, Message, Precis):
    """
    This function displays a Message (passed as input) and gives and error
    in case the matrix passed to it is not integral.`
    """
    cond = int_man.int_check(CheckMatrix, Precis)
    print(
        Checknumber,
        '.',
        Message,
        '-> ',
    )
    txt = Col()
    if cond.all():
        txt.c_prnt('YES', 'yel')
    else:
        txt.c_prnt('<<<Error>>>', 'amber')
        raise Exception('Something wrong!!')
Beispiel #6
0
def lll_reduction(matrix, delta=0.75):
    """
    _________________________________________________________________________
    This function has been borrowed from pymatgen project with slight changes
    in input and output handling.
    Link to the project:
        http://pymatgen.org/
    Link to the source code:
        https://github.com/materialsproject/pymatgen/blob/92ee88ab6a6ec6e27b717150931e6d484d37a4e6/pymatgen/core/lattice.py
    _________________________________________________________________________
    Performs a Lenstra-Lenstra-Lovasz lattice basis reduction to obtain a
    c-reduced basis. This method returns a basis which is as "good" as
    possible, with "good" defined by orthongonality of the lattice vectors.

    Args:
        delta (float): Reduction parameter. Default of 0.75 is usually
            fine.
    Returns:
        Reduced lattice.
    """

    if int_man.int_check(matrix, 10).all():

        # Transpose the lattice matrix first so that basis vectors are columns.
        # Makes life easier.
        a = np.array(matrix)
        sz = a.shape

        b = np.zeros((3, 3))  # Vectors after the Gram-Schmidt process
        u = np.zeros((3, 3))  # Gram-Schmidt coeffieicnts
        m = np.zeros(3)  # These are the norm squared of each vec.

        b[:, 0] = a[:, 0]
        m[0] = np.dot(b[:, 0], b[:, 0])
        for i in xrange(1, sz[1]):
            u[i, 0:i] = np.dot(a[:, i].T, b[:, 0:i]) / m[0:i]
            b[:, i] = a[:, i] - np.dot(b[:, 0:i], u[i, 0:i].T)
            m[i] = np.dot(b[:, i], b[:, i])

        k = 2

        while k <= sz[1]:
            # Size reduction.
            for i in xrange(k - 1, 0, -1):
                q = round(u[k - 1, i - 1])
                if q != 0:
                    # Reduce the k-th basis vector.
                    a[:, k - 1] = a[:, k - 1] - q * a[:, i - 1]
                    uu = list(u[i - 1, 0:(i - 1)])
                    uu.append(1)
                    # Update the GS coefficients.
                    u[k - 1, 0:i] = u[k - 1, 0:i] - q * np.array(uu)

            # Check the Lovasz condition.
            if np.dot(b[:, k - 1], b[:, k - 1]) >=\
                    (delta - abs(u[k - 1, k - 2]) ** 2) *\
                    np.dot(b[:, (k - 2)], b[:, (k - 2)]):
                # Increment k if the Lovasz condition holds.
                k += 1
            else:
                # If the Lovasz condition fails,
                # swap the k-th and (k-1)-th basis vector
                v = a[:, k - 1].copy()
                a[:, k - 1] = a[:, k - 2].copy()
                a[:, k - 2] = v
                # Update the Gram-Schmidt coefficients
                for s in xrange(k - 1, k + 1):
                    u[s - 1, 0:(s - 1)] = np.dot(
                        a[:, s - 1].T, b[:, 0:(s - 1)]) / m[0:(s - 1)]
                    b[:, s - 1] = a[:, s - 1] - np.dot(b[:, 0:(s - 1)],
                                                       u[s - 1, 0:(s - 1)].T)
                    m[s - 1] = np.dot(b[:, s - 1], b[:, s - 1])

                if k > (sz[1] - 1):
                    k -= 1
                else:
                    # We have to do p/q, so do lstsq(q.T, p.T).T instead.
                    p = np.dot(a[:, k:sz[1]].T, b[:, (k - (sz[1] - 1)):k])
                    q = np.diag(m[(k - (sz[1] - 1)):k])
                    result = np.linalg.lstsq(q.T, p.T)[0].T
                    u[k:sz[1], (k - (sz[1] - 1)):k] = result

        # checking if the reduced matrix is right handed
        # if np.linalg.det(a) < 0:
        #     a[:, [1, 2]] = a[:, [2, 1]]
        return a
    else:
        raise Exception(
            'The input to the lll_algorithm is expected to be integral')
Beispiel #7
0
def dsc_finder(L_G2_G1, L_G1_GO1):
    """
    The DSC lattice is computed for the bi-crystal, if the transformation
    matrix l_g2_g1 is given and the basis vectors of the underlying crystal
    l_g_go (in the orthogonal reference go frame) are known. The following
    relationship is used: **The reciprocal of the coincidence site lattice of
    the reciprocal lattices is the DSC lattice**

    Parameters
    ----------------
    l_g2_g1: numpy array
    transformation matrix (r_g1tog2_g1)

    l_g1_go1: numpy array
    basis vectors (as columns) of the underlying lattice expressed in the
    orthogonal 'go' reference frame

    Returns
    ------------
    l_dsc_g1: numpy array
    The dsc lattice basis vectors (as columns) expressed in the g1 reference

    Notes
    ---------
    The "Reduced" refer to the use of LLL algorithm to compute a
    basis that is as close to orthogonal as possible.
    (Refer to http://en.wikipedia.org/wiki/Lattice_reduction) for further
    detials on the concept of Lattice Reduction
    """

    L_G2_G1 = np.array(L_G2_G1)
    L_G1_GO1 = np.array(L_G1_GO1)

    L_GO1_G1 = np.linalg.inv(L_G1_GO1)
    # % % Reciprocal lattice of G1
    # --------------------------------------------------------------
    L_rG1_GO1 = reciprocal_mat(L_G1_GO1)
    L_GO1_rG1 = np.linalg.inv(L_rG1_GO1)
    # L_rG1_G1 = np.dot(L_GO1_G1, L_rG1_GO1)
    # % % L_G1_rG1 = L_rG1_G1^(-1);
    # % % Reciprocal lattice of G2
    L_G2_GO1 = np.dot(L_G1_GO1, L_G2_G1)
    L_rG2_GO1 = reciprocal_mat(L_G2_GO1)

    # % % Transformation of the Reciprocal lattices
    # % % R_rG1TorG2_rG1 = L_rG2_G1*L_G1_rG1;
    L_rG2_rG1 = np.dot(L_GO1_rG1, L_rG2_GO1)
    Sigma_star = sigma_calc(L_rG2_rG1)

    # % % CSL of the reciprocal lattices
    L_rCSL_rG1 = csl_finder_smith(L_rG2_rG1)
    L_rCSL_GO1 = np.dot(L_rG1_GO1, L_rCSL_rG1)
    # % % Reciprocal of the CSL of the reciprocal lattices
    L_DSC_GO1 = reciprocal_mat(L_rCSL_GO1)
    L_DSC_G1 = np.dot(L_GO1_G1, L_DSC_GO1)

    # % % Reduction of the DSC lattice in G1 reference frame
    DSC_Int = int_man.int_finder(L_DSC_G1, 1e-06)
    t_ind = np.where(abs(DSC_Int) == abs(DSC_Int).max())
    t_ind_1 = t_ind[0][0]
    t_ind_2 = t_ind[1][0]
    Mult1 = DSC_Int[t_ind_1, t_ind_2] / L_DSC_G1[t_ind_1, t_ind_2]
    DSC_Reduced = lll_reduction(DSC_Int)
    DSC_Reduced = DSC_Reduced / Mult1
    L_DSC_G1 = DSC_Reduced

    # % % % Check this assertion: L_DSC_G1 = [Int_Matrix]/Sigma
    if int_man.int_check(Sigma_star*L_DSC_G1, 10).all():
        L_DSC_G1 = np.around(Sigma_star*L_DSC_G1) / Sigma_star
    else:
        raise Exception('L_DSC_G1 is not equal to [Int_Matrix]/Sigma')
    return L_DSC_G1