Exemple #1
0
def GetPrimLattice(latt, pos, num, dictp):
    is_prim = None
    rot = np.identity(3)
    tr = SymTrans(rot, dictp, num, pos, latt)
    #print('tr:\n', tr)
    if tr is not None:
        if len(tr) == 1:
            print('Input cell is primitive!')
            is_prim = 1  # // primitive cell flag
            #print('primitive lattice:\n', latt)  # // delaunay of primitive lattice vec
            #print('primitive numbers:\n', num)
            #print('primitive cell positions:\n', pos)  # atom postion
            #return latt, num, pos
            #// delaunay change part
            flag, reduc_b, delauP = delaunay.Delaunay(latt, -1)
            if flag:
                new_pos = delaunay.ChangeOfBasis(pos, np.linalg.inv(delauP))
                print('primitive lattice (delaunay):\n',
                      reduc_b)  # // delaunay of primitive lattice vec
                print('primitive cell positions:\n',
                      [list(i) for i in new_pos])  # atom postion
                return reduc_b, num, new_pos, is_prim
        else:
            print('Input cell is not primitive! Changing...')
            is_prim = 0  # // convetional cell flag
            ori_tr = [
                np.array([1.000000000, 0.0000000000, 0.0000000000]),
                np.array([0.000000000, 1.0000000000, 0.0000000000]),
                np.array([0.000000000, 0.0000000000, 1.0000000000])
            ]
            #print('original:\n', ori_tr)
            prim_vec = tr[1:] + ori_tr  # delete the first vec in tr (ori-ori)
            print('all primitive translations:\n', prim_vec)
            #min_prim_latt = np.zeros((3, 3))
            flag3, min_prim_latt = check_volume1(
                prim_vec, latt)  # // delaunay of primitive lattice vec
            if flag3 == 'Found':
                #print('final primitive lattice\n', min_prim_latt)
                #prim_latt, new_num, new_pos = AtomPosConv2Prim(min_prim_latt, latt, pos, num)
                #return prim_latt, new_num, new_pos
                #print('new numbers:\n', new_num)
                #print('new positions:\n', new_pos)
                # // delaunay change part
                flag, reduc_b, delaup = delaunay.Delaunay(min_prim_latt, -1)
                if flag:
                    print('primitive lattice (delaunay):\n', reduc_b)
                    reduc_latt, new_num, new_pos = AtomPosConv2Prim(
                        reduc_b, latt, pos, num)
                    print('primitive cell positions:\n',
                          [list(i) for i in new_pos])  # atom postion
                    return reduc_latt, new_num, new_pos, is_prim
Exemple #2
0
def GetStandardPos(std_latt, pos, num, trans_matrix, center, is_prim, origin, prim_flag=False):
    # Get standard positions
    tp_positions = []
    positions = []
    std_num = []
    std_pos = []
    if is_prim:
        tp1_positions = delaunay.ChangeOfBasis(pos, np.linalg.inv(trans_matrix))
        tp = np.zeros(3)
        for i in tp1_positions:
            tp_positions.append(np.array(i) + origin)  # // Xc~ = Q * Xp + Pc

        shift = [[0, 0, 0]]
        if center == 'A_FACE':
            shift.append([0, 0.5, 0.5])

        elif center == 'B_FACE':
            shift.append([0.5, 0, 0.5])

        elif center == 'C_FACE':
            shift.append([0.5, 0.5, 0])

        elif center == 'BODY':
            shift.append([0.5, 0.5, 0.5])

        elif center == 'R_CENTER':
            shift.append([2. / 3, 1. / 3, 1. / 3])
            shift.append([1. / 3, 2. / 3, 2. / 3])

        elif center == 'FACE':
            shift.append([0, 0.5, 0.5])
            shift.append([0.5, 0, 0.5])
            shift.append([0.5, 0.5, 0])

        # new_pos = np.zeros(3)
        for j in range(len(tp_positions)):
            for i in range(len(shift)):
                new_pos = np.array(tp_positions[j]) + np.array(shift[i])
                tp2 = new_pos.copy()
                for k in range(3):
                    if tp2[k] < 0.0:
                        tp2[k] = int(tp2[k] - 0.5)
                    else:
                        tp2[k] = int(tp2[k] + 0.5)
                new_pos = new_pos - tp2
                for k in range(3):
                    if new_pos[k] < 0.0:
                        new_pos[k] += 1.0
                positions.append(new_pos)  # // Xc = Xc~ + shift vec
        # print('cek1', positions)

        for j in num:
            for i in range(len(shift)):
                std_num.append(j)

        # adjust positions to list format
        for i in positions:
            tp = []
            for j in i:
                tp.append(j)
            std_pos.append(tp)

    else:
        # input is conventional
        tp_positions = delaunay.ChangeOfBasis(pos, np.linalg.inv(trans_matrix))
        for i in tp_positions:
            positions.append(np.array(i) + origin)

        # adjust positions to list format
        for i in positions:
            tp = []
            for j in i:
                tp.append(j)
            std_pos.append(tp)

        std_num = num.copy()
        # print('cek1', positions)

    if is_prim or prim_flag:
        print('standard conventional lattice:\n', std_latt)
        print('standard conventional numbers:\n', std_num)
        print('standard conventional positions:\n', std_pos)
        return StandardPrimCell(std_latt, std_pos, std_num, center)
    else:
        return std_latt, std_num, std_pos
Exemple #3
0
def AtomPosPrim2Conv(prim_latt, latt, pos, num, cel_size):
    latt_vol = np.linalg.det(latt)
    prim_vol = np.linalg.det(prim_latt)
    ratio = latt_vol / prim_vol
    print('ratio1:\n', ratio)
    #cel_size = len(pos)

    ratio = np.around(ratio, decimals=3)
    ratio = abs(ratio)
    print('ratio2:\n', ratio)

    inv_tp_vec = np.linalg.inv(latt)
    P = np.transpose(np.dot(prim_latt, inv_tp_vec))  # P, Q is a vertical vec
    Q = np.linalg.inv(P)
    print('check Q1: ', np.linalg.det(Q))

    deterQ = np.around(np.linalg.det(Q), decimals=3)
    print('check Q2: ', deterQ)

    if abs(
            deterQ
    ) != ratio:  # P: big(conv) --> small(prim). so P is no larger than 1, Q is no smaller than 1
        print('Error1')
        return None, None, None

    if (cel_size / ratio) * ratio != cel_size:
        print('Error2')
        return None, None, None

    tp_new_pos = delaunay.ChangeOfBasis(pos, Q)
    #print('temp_postion1:\n', tp_new_pos)

    new_site = []
    tolerance = 0.00001
    for i in range(cel_size):
        new_site.append(
            i
        )  # // note: maybe index is out of range if it isn't intialized with len(cel_size)
    for cnt in range(100):
        for i in range(cel_size):
            for j in range(cel_size):
                if num[i] == num[j]:
                    if VecIsOverlap(np.array(tp_new_pos[i]),
                                    np.array(tp_new_pos[j]), prim_latt,
                                    tolerance):
                        if new_site[j] == j:
                            new_site[
                                i] = j  # // change the equiv to the first showed one
                            break
    #print('new site:\n', new_site)

    new_num = []
    for i in set(new_site):
        new_num.append(num[i])  # // ['Zr', 'O', 'O']
    print('check!', new_num)

    tp_p = []
    for i in new_site:
        tp_p.append(
            tp_new_pos[i]
        )  # // atom sites according to the new_site ['Zr', 'O', 'O']
    #print('temp_postion2:\n', tp_p)

    # // boundary trim
    new_posi = []
    for i in range(cel_size):
        new_posi.append(np.zeros(3))

    for i in range(cel_size):
        for j in range(3):
            if abs(tp_new_pos[i][j] - tp_p[i][j]) > 0.5:
                if tp_new_pos[i][j] < tp_p[i][j]:
                    new_posi[new_site[i]][j] += tp_new_pos[i][j] + 1
                else:
                    new_posi[new_site[i]][j] += tp_new_pos[i][j] - 1
            else:
                new_posi[new_site[i]][j] = tp_new_pos[i][j]

        # // average of the overlapped two atoms
        ave_pos = cel_size / len(new_posi)
        for j in range(len(new_posi)):
            #tp2 = np.zeros(3)
            for k in range(3):
                new_posi[j][k] = new_posi[j][k] / ave_pos
            tp2 = new_posi[j].copy(
            )  # // Watch out! Don't use "tp2 = new_posi[j]", otherwise they will change at the same time
            for k in range(3):
                if tp2[k] < 0.0:
                    tp2[k] = int(tp2[k] - 0.5)
                else:
                    tp2[k] = int(tp2[k] + 0.5)
            new_posi[j] = new_posi[j] - tp2
            for k in range(3):
                if new_posi[j][k] < 0.0:
                    new_posi[j][k] += 1.0

    new_pos = []
    for i in set(new_site):
        new_pos.append(new_posi[i])

    print('new numbers:\n', new_num)
    print('new positions:\n', [list(i) for i in new_pos])

    return prim_latt, new_num, new_pos
Exemple #4
0
def AtomPosConv2Prim(prim_latt, latt, pos, num):
    """
        Conventional lattice changes to primitive lattice
        Find correspoing new atomic positions (for primitive)
    """

    latt_vol = np.linalg.det(latt)
    prim_vol = np.linalg.det(prim_latt)
    ratio = latt_vol / prim_vol

    cel_size1 = len(pos)

    if ratio < 0.0:
        ratio = int(ratio - 0.5)
    else:
        ratio = int(ratio + 0.5)

    ratio = abs(ratio)
    #print('ratio2:\n', ratio)

    inv_tp_vec = np.linalg.inv(latt)
    P = np.transpose(np.dot(prim_latt, inv_tp_vec))  # P, Q : vertical vectors
    Q = np.linalg.inv(P)
    # print('check Q1: ', np.linalg.det(Q))

    for i in range(3):
        for j in range(3):
            if Q[i, j] < 0.0:
                Q[i, j] = int(Q[i, j] - 0.5)
            else:
                Q[i, j] = int(Q[i, j] + 0.5)
    # print('check Q2: ', np.linalg.det(Q))

    # P: big(conv) --> small(prim)
    # P is no larger than 1, but Q is no smaller than 1
    if abs(np.linalg.det(Q)) != ratio:
        print('Error1')
        return None, None, None

    if (cel_size1 / ratio) * ratio != cel_size1:
        print('Error2')
        return None, None, None

    tp_new_pos = delaunay.ChangeOfBasis(pos, Q)
    #print('temp_postion1:\n', tp_new_pos)

    new_site = []
    tolerance = 0.00001

    # note: index maybe out of range if it isn't initialized with len(cel_size)
    for i in range(cel_size1):
        new_site.append(i)

    for cnt in range(100):
        for i in range(cel_size1):
            for j in range(cel_size1):
                if num[i] == num[j]:
                    if VecIsOverlap(np.array(tp_new_pos[i]),
                                    np.array(tp_new_pos[j]), prim_latt,
                                    tolerance):
                        # change the equivalent to the first showed one
                        if new_site[j] == j:
                            new_site[i] = j
                            break
    # print('new site:\n', new_site)

    new_num = []
    for i in sorted(set(new_site)):
        new_num.append(num[i])  # test: ['Zr', 'O', 'O']

    # print('check!', new_num)

    tp_p = []
    for i in new_site:
        tp_p.append(
            tp_new_pos[i]
        )  # test: atomic sites according to the new_site ['Zr', 'O', 'O']

    # boundary trim
    new_posi = []
    for i in range(cel_size1):
        new_posi.append(np.zeros(3))

    for i in range(cel_size1):
        for j in range(3):
            if abs(tp_new_pos[i][j] - tp_p[i][j]) > 0.5:
                if tp_new_pos[i][j] < tp_p[i][j]:
                    new_posi[new_site[i]][j] += tp_new_pos[i][j] + 1
                else:
                    new_posi[new_site[i]][j] += tp_new_pos[i][j] - 1
            else:
                new_posi[new_site[i]][j] = tp_new_pos[i][j]

        # average of the overlapped two atoms
        ave_pos = cel_size1 / len(new_posi)
        for j in range(len(new_posi)):
            #tp2 = np.zeros(3)
            for k in range(3):
                new_posi[j][k] = new_posi[j][k] / ave_pos

            # Note: Don't use "tp2 = new_posi[j]" (change at the same time)
            tp2 = new_posi[j].copy()
            for k in range(3):
                if tp2[k] < 0.0:
                    tp2[k] = int(tp2[k] - 0.5)
                else:
                    tp2[k] = int(tp2[k] + 0.5)

            new_posi[j] = new_posi[j] - tp2
            for k in range(3):
                if new_posi[j][k] < 0.0:
                    new_posi[j][k] += 1.0

    new_pos = []
    for i in sorted(set(new_site)):
        new_pos.append(new_posi[i])

    print('new numbers:\n', new_num)
    print('new positions:\n', [list(i) for i in new_pos])

    return prim_latt, new_num, new_pos