예제 #1
0
def get_fc2_coefficients(pairs_orig, mapping_pair, transform_pair, lattice,
                         positions, rots1, trans1, ind_atoms1, mappings1,
                         map_ope1, rots2, mappings2, map_ope2):
    natom = len(positions)
    pairs_reduced = [pairs_orig[i] for i in np.unique(mapping_pair)]
    coeff = np.zeros((natom, natom, 9, 9), dtype=np.float)
    ifc_map = np.zeros((natom, natom), dtype="intc")
    for atom1 in np.arange(natom):
        r1, t = rots1[map_ope1[atom1]], trans1[map_ope1[atom1]]
        a1 = mappings1[atom1]
        index1 = np.where(
            ind_atoms1 == a1)[0][0]  # index of the first irreducible atom
        site_symmetries = rots2[index1]  #[:nope[index1]]
        for atom2 in np.arange(natom):
            map_atom2 = get_atom_sent_by_operation(atom2, positions, r1, t)
            a2 = mappings2[index1][map_atom2]
            r2 = site_symmetries[map_ope2[index1, map_atom2]]
            R = np.dot(r2, r1)  # from original to irreducible pair
            R_cart = np.double(similarity_transformation(lattice, R))
            # coeff_temp = np.einsum("ij, kl -> ikjl", R_cart, R_cart).reshape(9,9)
            coeff_temp = np.kron(R_cart.T, R_cart.T)
            index_orig = pairs_orig.index((a1, a2))
            star2 = pairs_orig[mapping_pair[index_orig]]
            ifc_map[atom1, atom2] = pairs_reduced.index(star2)
            permu_trans = transform_pair[index_orig]
            coeff_temp = np.dot(coeff_temp, permu_trans)
            #take the permutation matrix into consideration
            coeff[atom1, atom2] = coeff_temp[:]  # inverse equals transpose
    return coeff, ifc_map
예제 #2
0
def get_fc2_coefficient_and_mapping(doublets_reduced, pairs, symmetry, cell):
    natom = cell.get_number_of_atoms()
    positions = cell.get_scaled_positions()
    coeff = np.zeros((natom, natom, 9, 9), dtype=np.float)
    ifc_map = np.zeros((natom, natom), dtype="intc")
    lattice = cell.get_cell().T
    for atom1 in np.arange(natom):
        nmap = symmetry.get_map_operations()[atom1]
        map_syms = symmetry.get_symmetry_operation(nmap)
        a1 = symmetry.get_map_atoms()[atom1]
        index1 = np.where(symmetry.get_independent_atoms() == a1)[0][0] # index of the first irreducible atom
        site_symmetries = pairs[index1]['site_symmetry']
        r1 = map_syms['rotations']
        t = map_syms['translations']
        for atom2 in np.arange(natom):
            map_atom2 = get_atom_sent_by_operation(atom2, positions, r1, t)
            a2 = pairs[index1]['mapping'][map_atom2]
            index2 = np.where(pairs[index1]['independent_atoms'] == a2)[0][0]# index of the second irreducible atom
            r2 = site_symmetries[pairs[index1]['mapping_operation'][map_atom2]]
            R = np.dot(r2, r1)
            R_cart = np.double(similarity_transformation(lattice, R))
            coeff_temp = np.einsum("ij, kl -> ikjl", R_cart, R_cart).reshape(9,9)
            star2 = pairs[index1]['next_atoms'][index2]
            if star2['tunnel'] is None:
                ifc_map[atom1, atom2] = doublets_reduced.index((a1, a2))
            else:
                i1, i2 = star2['tunnel']['star']
                a1 = pairs[i1]['atom_number']
                a2 = pairs[i1]['next_atoms'][i2]['atom_number']
                permu_trans = star2['tunnel']['transformation']
                ifc_map[atom1, atom2] = doublets_reduced.index((a1, a2))
                coeff_temp = np.dot(permu_trans, coeff_temp)
                #take the permutation matrix into consideration
            coeff[atom1, atom2] = coeff_temp.T # inverse equals transpose
    return coeff, ifc_map
예제 #3
0
def get_pairs_with_permute(pairs, lattice, positions, rots1, trans1,
                           ind_atoms1, mappings1, map_ope1, rots2, mappings2,
                           map_ope2):
    ########set permutation symmetry################
    pairs_mapping = np.arange(len(pairs))
    transform = np.zeros((len(pairs), 9, 9), dtype=np.float)
    transform[:] = np.eye(9)  # An identity matrix is broadcast
    for i, (atom1, atom2) in enumerate(pairs):
        #Execute the permutation
        patom1, patom2 = atom2, atom1
        iratom1 = mappings1[patom1]
        index1 = np.where(
            ind_atoms1 == iratom1)[0][0]  # index of the first irreducible atom
        numope = map_ope1[patom1]  #number of symmetry operation
        rot, tran = rots1[numope], trans1[numope]
        iratom2 = get_atom_sent_by_operation(patom2, positions, rot, tran)
        rot2 = rots2[index1][map_ope2[index1, iratom2]]
        iratom2 = mappings2[index1, iratom2]
        index_pair = pairs.index((iratom1, iratom2))
        if pairs_mapping[index_pair] < i:
            pairs_mapping[i] = pairs_mapping[index_pair]
            transf = np.dot(rot2, rot)
            trans_cart = similarity_transformation(lattice, transf)
            trans_tensor = np.kron(trans_cart.T, trans_cart.T).reshape(
                3, 3, 9)  # from irreducible to general mapping
            trans_permute = trans_tensor.swapaxes(0, 1).reshape(
                9, 9)  # permutation of the original fc2
            # transf = np.einsum("ij,km -> kijm", trans_cart, trans_cart).reshape(9,9)
            transform[i] = np.dot(trans_permute, transform[index_pair])
        else:
            transform[i] = np.eye(9)
    return pairs_mapping, transform
예제 #4
0
def get_fc2_coefficients(pairs_orig,
                         mapping_pair,
                         transform_pair,
                         lattice,
                         positions,
                         rots1,
                         trans1,
                         ind_atoms1,
                         mappings1,
                         map_ope1,
                         rots2,
                         mappings2,
                         map_ope2):
    natom = len(positions)
    pairs_reduced = [pairs_orig[i] for i in np.unique(mapping_pair)]
    coeff = np.zeros((natom, natom, 9, 9), dtype=np.float)
    ifc_map = np.zeros((natom, natom), dtype="intc")
    for atom1 in np.arange(natom):
        r1, t = rots1[map_ope1[atom1]], trans1[map_ope1[atom1]]
        a1 = mappings1[atom1]
        index1 = np.where(ind_atoms1 == a1)[0][0] # index of the first irreducible atom
        site_symmetries = rots2[index1] #[:nope[index1]]
        for atom2 in np.arange(natom):
            map_atom2 = get_atom_sent_by_operation(atom2, positions, r1, t)
            a2 = mappings2[index1][map_atom2]
            r2 = site_symmetries[map_ope2[index1,map_atom2]]
            R = np.dot(r2, r1) # from original to irreducible pair
            R_cart = np.double(similarity_transformation(lattice, R))
            # coeff_temp = np.einsum("ij, kl -> ikjl", R_cart, R_cart).reshape(9,9)
            coeff_temp = np.kron(R_cart.T, R_cart.T)
            index_orig = pairs_orig.index((a1, a2))
            star2 = pairs_orig[mapping_pair[index_orig]]
            ifc_map[atom1, atom2] = pairs_reduced.index(star2)
            permu_trans = transform_pair[index_orig]
            coeff_temp = np.dot(coeff_temp, permu_trans)
            #take the permutation matrix into consideration
            coeff[atom1, atom2] = coeff_temp[:] # inverse equals transpose
    return coeff, ifc_map
예제 #5
0
def get_fc2_coefficient_and_mapping(doublets_reduced, pairs, symmetry, cell):
    natom = cell.get_number_of_atoms()
    positions = cell.get_scaled_positions()
    coeff = np.zeros((natom, natom, 9, 9), dtype=np.float)
    ifc_map = np.zeros((natom, natom), dtype="intc")
    lattice = cell.get_cell().T
    for atom1 in np.arange(natom):
        nmap = symmetry.get_map_operations()[atom1]
        map_syms = symmetry.get_symmetry_operation(nmap)
        a1 = symmetry.get_map_atoms()[atom1]
        index1 = np.where(symmetry.get_independent_atoms() == a1)[0][
            0]  # index of the first irreducible atom
        site_symmetries = pairs[index1]['site_symmetry']
        r1 = map_syms['rotations']
        t = map_syms['translations']
        for atom2 in np.arange(natom):
            map_atom2 = get_atom_sent_by_operation(atom2, positions, r1, t)
            a2 = pairs[index1]['mapping'][map_atom2]
            index2 = np.where(pairs[index1]['independent_atoms'] == a2)[0][
                0]  # index of the second irreducible atom
            r2 = site_symmetries[pairs[index1]['mapping_operation'][map_atom2]]
            R = np.dot(r2, r1)
            R_cart = np.double(similarity_transformation(lattice, R))
            coeff_temp = np.einsum("ij, kl -> ikjl", R_cart,
                                   R_cart).reshape(9, 9)
            star2 = pairs[index1]['next_atoms'][index2]
            if star2['tunnel'] is None:
                ifc_map[atom1, atom2] = doublets_reduced.index((a1, a2))
            else:
                i1, i2 = star2['tunnel']['star']
                a1 = pairs[i1]['atom_number']
                a2 = pairs[i1]['next_atoms'][i2]['atom_number']
                permu_trans = star2['tunnel']['transformation']
                ifc_map[atom1, atom2] = doublets_reduced.index((a1, a2))
                coeff_temp = np.dot(permu_trans, coeff_temp)
                #take the permutation matrix into consideration
            coeff[atom1, atom2] = coeff_temp.T  # inverse equals transpose
    return coeff, ifc_map
예제 #6
0
def get_pairs_with_permute(pairs,
                           lattice,
                           positions,
                           rots1,
                           trans1,
                           ind_atoms1,
                           mappings1,
                           map_ope1,
                           rots2,
                           mappings2,
                           map_ope2):
########set permutation symmetry################
    pairs_mapping = np.arange(len(pairs))
    transform = np.zeros((len(pairs), 9, 9), dtype=np.float)
    transform[:] = np.eye(9) # An identity matrix is broadcast
    for i, (atom1, atom2) in enumerate(pairs):
        #Execute the permutation
        patom1, patom2 = atom2, atom1
        iratom1 = mappings1[patom1]
        index1 = np.where(ind_atoms1 == iratom1)[0][0] # index of the first irreducible atom
        numope = map_ope1[patom1] #number of symmetry operation
        rot, tran = rots1[numope], trans1[numope]
        iratom2 = get_atom_sent_by_operation(patom2, positions, rot, tran)
        rot2 = rots2[index1][map_ope2[index1, iratom2]]
        iratom2 = mappings2[index1, iratom2]
        index_pair = pairs.index((iratom1, iratom2))
        if pairs_mapping[index_pair] < i:
            pairs_mapping[i] = pairs_mapping[index_pair]
            transf = np.dot(rot2, rot)
            trans_cart = similarity_transformation(lattice, transf)
            trans_tensor = np.kron(trans_cart.T, trans_cart.T).reshape(3,3,9) # from irreducible to general mapping
            trans_permute = trans_tensor.swapaxes(0,1).reshape(9,9) # permutation of the original fc2
            # transf = np.einsum("ij,km -> kijm", trans_cart, trans_cart).reshape(9,9)
            transform[i] = np.dot(trans_permute, transform[index_pair])
        else:
            transform[i] = np.eye(9)
    return pairs_mapping, transform
예제 #7
0
def get_fc2_spg_invariance(pairs_orig,
                           positions,
                           rotations1,
                           translations1,
                           mappings1,
                           rotations2,
                           num_rotations2,
                           mappings2,
                           lattice,
                           symprec):
    indatoms1 = np.unique(mappings1)
    doublets_dict = []
    for index_pair,pair in enumerate(pairs_orig):
        doublet_dict = {}
        CC = [np.zeros(9)]
        for permute in list(permutations([0,1])):
            rot_all = []
            atom1, atom2= [pair[i] for i in permute]
            if not mappings1[atom1] == pair[0]:
                continue
            for numope in get_all_operations_at_star(rotations1,
                                                     translations1,
                                                     positions,
                                                     atom1,
                                                     mappings1,
                                                     symprec):
                #get all the symmetry operation that keeps atom1 unchanged
                rot1, tran = rotations1[numope], translations1[numope]
                atom1_1 = mappings1[atom1]
                index1 = np.where(indatoms1 == atom1_1)[0][0] # index of the first irreducible atom
                atom2_1 = get_atom_sent_by_operation(atom2, positions, rot1, tran, symprec=symprec)
                site_syms = rotations2[index1][:num_rotations2[index1]]
                if mappings2[index1, atom2_1] != pair[1]:
                    continue
                for rot2 in get_rotations_at_star(site_syms, positions, atom1_1, atom2_1, mappings2[index1], symprec):
                    rot = np.dot(rot2, rot1)
                    isfound = False
                    for r in rot_all:
                        if (np.abs(r-rot) < symprec).all():
                            isfound = True
                            break
                    if not isfound:
                        rot_all.append(rot)
                    else:
                        continue
                    rot_cart = np.double(similarity_transformation(lattice, rot))
                    seq = "".join(["ik"[i] for i in permute])
                    PP  = np.einsum("ij,kl -> %sjl"%seq, rot_cart, rot_cart).reshape(9, 9).T
                    BB = PP - np.eye(9)
                    for i in np.arange(9):
                        is_found = False
                        if not (np.abs(BB[i]) < symprec).all():
                            for j in np.arange(len(CC)):
                                if (np.abs(BB[i] - CC[j]) < symprec).all():
                                    is_found = True
                                    break
                            if not is_found:
                                CC.append(BB[i])
        CC, transform, independent = gaussian(np.array(CC))
        doublet_dict['independent'] = [ind + index_pair * 9 for ind in independent] # independent ele
        doublet_dict['transform'] = transform
        doublets_dict.append(doublet_dict)
    num_irred = [len(dic['independent']) for dic in doublets_dict]
    trans = np.zeros((len(doublets_dict), 9, sum(num_irred)), dtype="float")
    for i, doub  in enumerate(doublets_dict):
        start = sum(num_irred[:i])
        length = num_irred[i]
        trans[i,:, start:start + length] = doub['transform']
    return np.hstack((dic['independent'] for dic in doublets_dict)), trans
예제 #8
0
def get_irreducible_triplets_with_permute(
        triplets, positions, rotations1, translations1, mappings1,
        mapping_opes1, rotations2, num_rotations2, mappings2, mapping_opes2,
        rotations3, num_rotations3, mappings3, mapping_opes3, lattice,
        symprec):
    triplets_mapping = np.arange(len(triplets))
    transform = np.zeros((len(triplets), 27, 27), dtype='double')
    transform[:] += np.eye(27)
    indatoms1 = np.unique(mappings1)
    for itriplet, (p1, p2, p3) in enumerate(triplets):
        triplet = (p1, p2, p3)
        # if triplet == (0, 5, 15):
        #     print "good"
        for permute in list(permutations(
            [0, 1, 2]))[1:]:  # Leave out the original triplet
            atom1, atom2, atom3 = [triplet[i]
                                   for i in permute]  # permuted triplet
            if triplet == (atom1, atom2, atom3):
                continue
                # atom1 = triplet[permute_matrix[0]];atom2 = triplet[permute_matrix[1]]; atom3 = triplet[permute_matrix[2]] # permuted triplet
            numope = mapping_opes1[atom1]  #number of symmetry operation
            rot, tran = rotations1[numope], translations1[numope]
            atom1 = mappings1[atom1]
            atom2 = get_atom_sent_by_operation(atom2,
                                               positions,
                                               rot,
                                               tran,
                                               symprec=symprec)
            atom3 = get_atom_sent_by_operation(atom3,
                                               positions,
                                               rot,
                                               tran,
                                               symprec=symprec)
            # atom1 is transformed to an independent atom and atom2 and atom3 are transformed following atom1
            index1 = np.where(indatoms1 == atom1)[0][
                0]  # index of the first irreducible atom
            site_sym = rotations2[index1][:num_rotations2[index1]]
            mapping2 = mappings2[
                index1]  # now atom1 would be fixed under its site symmetries
            iatoms2 = np.unique(mappings2[index1])
            rot2 = site_sym[mapping_opes2[index1, atom2]]
            # a rotation which transforms atom2 to an independent one under site symmetries
            atom2 = mapping2[atom2]
            atom3 = get_atom_sent_by_site_sym(atom3,
                                              atom1,
                                              positions,
                                              rot2,
                                              symprec=symprec)
            # atom3 is transformed following atom2
            index2 = np.where(
                iatoms2 == atom2)[0][0]  # index of the second irreducible atom
            site_sym3 = rotations3[index1, index2, :num_rotations3[index1,
                                                                   index2]]
            map_ope3 = mapping_opes3[index1, index2]
            mapping3 = mappings3[index1, index2]
            rot3 = site_sym3[map_ope3[atom3]]
            atom3 = mapping3[
                atom3]  # atom3 is also transformed to an irreducible one under bond symmetries
            triplet_permute = (atom1, atom2, atom3)
            # Check if triplet_permute already exists in the triplets pool
            permuted_index = triplets.index(triplet_permute)
            if triplets_mapping[permuted_index] < triplets_mapping[itriplet]:
                triplets_mapping[itriplet] = triplets_mapping[permuted_index]
                transf = np.dot(rot3, np.dot(rot2, rot))
                transf_cart = similarity_transformation(
                    lattice, transf
                ).T  # Coordinate transform from  irreducible to general
                seq = "".join(['ikm'[permute.index(i)] for i in range(3)
                               ])  # find the original index before permutation
                transform_temp = np.einsum("ij, kl, mn -> %sjln" % seq,
                                           transf_cart, transf_cart,
                                           transf_cart).reshape(27, 27)
                transform[itriplet] = np.dot(
                    transform_temp,
                    transform[permuted_index])  # from irreducible to general
    return triplets_mapping, transform
예제 #9
0
def get_fc3_spg_invariance(triplets,
                           positions,
                           rotations1,
                           translations1,
                           mappings1,
                           rotations2,
                           num_rotations2,
                           mappings2,
                           rotations3,
                           num_rotations3,
                           mappings3,
                           lattice,
                           symprec,
                           is_disperse=False):
    "Find all spg symmetries that map the triplet to itself and thus the symmetry would act as constraints"
    triplets_dict = []
    iatoms1 = np.unique(mappings1)
    for itriplet, triplet in enumerate(triplets):
        triplet_dict = {}
        triplet_dict["triplet"] = triplet
        CC = [np.zeros(27)]

        for permute in list(permutations(
            [0, 1, 2])):  # Leave out the original triplet
            rot_all = []
            atom1, atom2, atom3 = [triplet[i] for i in permute]
            if not mappings1[atom1] == triplet[0]:
                continue
            for numope in get_all_operations_at_star(rotations1, translations1,
                                                     positions, atom1,
                                                     mappings1, symprec):
                #get all the symmetry operations that keep atom1 unchanged
                rot1, tran = rotations1[numope], translations1[numope]
                atom1_1 = mappings1[atom1]
                index1 = np.where(iatoms1 == atom1_1)[0][
                    0]  # index of the first irreducible atom
                atom2_1 = get_atom_sent_by_operation(atom2,
                                                     positions,
                                                     rot1,
                                                     tran,
                                                     symprec=symprec)
                atom3_1 = get_atom_sent_by_operation(atom3,
                                                     positions,
                                                     rot1,
                                                     tran,
                                                     symprec=symprec)
                site_syms = rotations2[index1, :num_rotations2[index1]]
                mapping2 = mappings2[
                    index1]  # now atom1 would be fixed under its site symmetries
                iatoms2 = np.unique(mapping2)
                if mapping2[atom2_1] != triplet[1]:
                    continue
                for rot2 in get_rotations_at_star(site_syms, positions,
                                                  atom1_1, atom2_1, mapping2,
                                                  symprec):
                    #get all the symmetry operations that keep both atom1 and atom2 unchanged
                    atom2_2 = mapping2[atom2_1]
                    atom3_2 = get_atom_sent_by_site_sym(
                        atom3_1, atom1_1, positions, rot2,
                        symprec=symprec)  #no matter atom1_1 or atom2_1
                    index2 = np.where(iatoms2 == atom2_2)[0][
                        0]  # index of the second irreducible atom
                    site_syms3 = rotations3[index1,
                                            index2, :num_rotations3[index1,
                                                                    index2]]
                    mapping3 = mappings3[index1, index2]
                    if not mapping3[atom3_2] == triplet[2]:
                        continue
                    for rot3 in get_rotations_at_star(site_syms3, positions,
                                                      atom2_2, atom3_2,
                                                      mapping3, symprec):
                        rot = np.dot(rot3, np.dot(rot2, rot1))
                        isfound = False
                        for r in rot_all:
                            if (np.abs(r - rot) < symprec).all():
                                isfound = True
                                break
                        if not isfound:
                            rot_all.append(rot)
                        else:
                            continue
                        # rot_cart = np.double(similarity_transformation(lattice, rot))
                        # seq = "".join(["ikm"[i] for i in permute])
                        # PP  = np.einsum("ij,kl,mn -> %sjln"%seq, rot_cart, rot_cart, rot_cart).reshape(27, 27).T

                        rot_cart = np.double(
                            similarity_transformation(lattice, rot)).T
                        seq = "".join([
                            'ikm'[permute.index(i)] for i in range(3)
                        ])  # find the original index before permutation
                        PP = np.einsum("ij,kl,mn -> %sjln" % seq, rot_cart,
                                       rot_cart, rot_cart).reshape(27, 27)
                        BB = PP - np.eye(27)
                        for i in np.arange(27):
                            is_found = False
                            if not (np.abs(BB[i]) < symprec).all():
                                row = BB[i] / np.abs(BB[i]).max()
                                for j in np.arange(len(CC)):
                                    if (np.abs(row - CC[j]) < symprec).all():
                                        is_found = True
                                        break
                                if not is_found:
                                    CC.append(row)
        DD = np.array(CC, dtype='double')
        CC, transform, independent = gaussian(DD)
        triplet_dict['independent'] = [
            ind + itriplet * 27 for ind in independent
        ]  # independent ele
        triplet_dict['transform'] = transform
        triplets_dict.append(triplet_dict)
    num_irred = [len(dic['independent']) for dic in triplets_dict]
    ind_elements = np.hstack((dic['independent'] for dic in triplets_dict))
    if is_disperse:
        from scipy.sparse import coo_matrix
        trans = []
        for i, trip in enumerate(triplets_dict):
            start = sum(num_irred[:i])
            length = num_irred[i]
            transform_tmp = np.zeros((27, sum(num_irred)), dtype="float")
            transform_tmp[:, start:start + length] = trip['transform']
            non_zero = np.where(np.abs(transform_tmp) > symprec)
            transform_tmp_sparse = coo_matrix(
                (transform_tmp[non_zero], non_zero), shape=transform_tmp.shape)
            trans.append(transform_tmp_sparse)
    else:
        trans = np.zeros((len(triplets_dict), 27, sum(num_irred)),
                         dtype="float")
        for i, trip in enumerate(triplets_dict):
            start = sum(num_irred[:i])

            length = num_irred[i]
            trans[i, :, start:start + length] = trip['transform']
    return ind_elements, trans
예제 #10
0
def get_fc3_coefficients(
        triplets_orig,
        mapping_triplet,
        transform_triplet,
        lattice,
        positions,
        rotations1,
        translations1,
        mappings1,
        map_ope1,
        rotations2,
        mappings2,
        map_ope2,
        rotations3,
        mappings3,
        map_ope3,
        symprec,
        first_atoms,
        triplet=None):  # returning the fc3 coefficients at a specific triplet
    natom = len(positions)
    ind_atoms1 = np.unique(mappings1)
    triplets_reduced = [triplets_orig[i] for i in np.unique(mapping_triplet)]
    if triplet is None:
        ifc_map = np.zeros((len(first_atoms), natom, natom), dtype=np.int16)
        coeff = np.zeros((len(first_atoms), natom, natom, 27, 27),
                         dtype=np.float)
        for i, atom1 in enumerate(first_atoms):
            iratom1 = mappings1[atom1]
            numope = map_ope1[atom1]
            index1 = np.where(ind_atoms1 == iratom1)[0][0]
            ind_atoms2 = np.unique(mappings2[index1])
            rot1, tran1 = rotations1[numope], translations1[numope]
            for atom2 in np.arange(natom):
                iratom2 = get_atom_sent_by_operation(atom2,
                                                     positions,
                                                     rot1,
                                                     tran1,
                                                     symprec=symprec)
                rot2 = rotations2[index1, map_ope2[index1, iratom2]]
                iratom2 = mappings2[index1, iratom2]
                index2 = np.where(ind_atoms2 == iratom2)[0][0]
                for atom3 in np.arange(natom):
                    iratom3 = get_atom_sent_by_operation(atom3,
                                                         positions,
                                                         rot1,
                                                         tran1,
                                                         symprec=symprec)
                    iratom3 = get_atom_sent_by_site_sym(iratom3,
                                                        iratom1,
                                                        positions,
                                                        rot2,
                                                        symprec=symprec)
                    rot3 = rotations3[index1, index2, map_ope3[index1, index2,
                                                               iratom3]]
                    iratom3 = mappings3[index1, index2, iratom3]
                    rot = np.dot(rot3, np.dot(rot2, rot1))
                    #rot transforms an arbitrary triplet to the irreducible one
                    index_triplet = triplets_orig.index(
                        (iratom1, iratom2, iratom3))
                    star3 = triplets_orig[mapping_triplet[index_triplet]]
                    ifc_map[i, atom2, atom3] = triplets_reduced.index(star3)
                    rot_cart = np.double(
                        similarity_transformation(
                            lattice, rot)).T  # from irreducible to general
                    coeff_temp = np.kron(np.kron(rot_cart, rot_cart), rot_cart)
                    coeff[i, atom2,
                          atom3] = np.dot(coeff_temp,
                                          transform_triplet[index_triplet])
                    # Considering the permutation symmetry previously obtained
    else:
        atom1, atom2, atom3 = triplet
        iratom1 = mappings1[atom1]
        numope = map_ope1[atom1]
        index1 = np.where(ind_atoms1 == iratom1)[0][0]
        ind_atoms2 = np.unique(mappings2[index1])
        rot1, tran1 = rotations1[numope], translations1[numope]
        iratom2 = get_atom_sent_by_operation(atom2,
                                             positions,
                                             rot1,
                                             tran1,
                                             symprec=symprec)
        rot2 = rotations2[index1, map_ope2[index1, iratom2]]
        iratom2 = mappings2[index1, iratom2]
        index2 = np.where(ind_atoms2 == iratom2)[0][0]
        iratom3 = get_atom_sent_by_operation(atom3,
                                             positions,
                                             rot1,
                                             tran1,
                                             symprec=symprec)
        iratom3 = get_atom_sent_by_site_sym(iratom3,
                                            iratom1,
                                            positions,
                                            rot2,
                                            symprec=symprec)
        rot3 = rotations3[index1, index2, map_ope3[index1, index2, iratom3]]
        iratom3 = mappings3[index1, index2, iratom3]
        rot = np.dot(rot3, np.dot(rot2, rot1))
        #rot transforms an arbitrary triplet to the irreducible one
        index_triplet = triplets_orig.index((iratom1, iratom2, iratom3))
        star3 = triplets_orig[mapping_triplet[index_triplet]]
        ifc_map = triplets_reduced.index(star3)
        rot_cart = np.double(similarity_transformation(
            lattice, rot)).T  # from irreducible to general
        coeff_temp = np.kron(np.kron(rot_cart, rot_cart), rot_cart)
        coeff = np.dot(coeff_temp, transform_triplet[index_triplet])
    return coeff, ifc_map
예제 #11
0
def get_fc2_spg_invariance(pairs_orig, positions, rotations1, translations1,
                           mappings1, rotations2, num_rotations2, mappings2,
                           lattice, symprec):
    indatoms1 = np.unique(mappings1)
    doublets_dict = []
    for index_pair, pair in enumerate(pairs_orig):
        doublet_dict = {}
        CC = [np.zeros(9)]
        for permute in list(permutations([0, 1])):
            rot_all = []
            atom1, atom2 = [pair[i] for i in permute]
            if not mappings1[atom1] == pair[0]:
                continue
            for numope in get_all_operations_at_star(rotations1, translations1,
                                                     positions, atom1,
                                                     mappings1, symprec):
                #get all the symmetry operation that keeps atom1 unchanged
                rot1, tran = rotations1[numope], translations1[numope]
                atom1_1 = mappings1[atom1]
                index1 = np.where(indatoms1 == atom1_1)[0][
                    0]  # index of the first irreducible atom
                atom2_1 = get_atom_sent_by_operation(atom2,
                                                     positions,
                                                     rot1,
                                                     tran,
                                                     symprec=symprec)
                site_syms = rotations2[index1][:num_rotations2[index1]]
                if mappings2[index1, atom2_1] != pair[1]:
                    continue
                for rot2 in get_rotations_at_star(site_syms, positions,
                                                  atom1_1, atom2_1,
                                                  mappings2[index1], symprec):
                    rot = np.dot(rot2, rot1)
                    isfound = False
                    for r in rot_all:
                        if (np.abs(r - rot) < symprec).all():
                            isfound = True
                            break
                    if not isfound:
                        rot_all.append(rot)
                    else:
                        continue
                    rot_cart = np.double(
                        similarity_transformation(lattice, rot))
                    seq = "".join(["ik"[i] for i in permute])
                    PP = np.einsum("ij,kl -> %sjl" % seq, rot_cart,
                                   rot_cart).reshape(9, 9).T
                    BB = PP - np.eye(9)
                    for i in np.arange(9):
                        is_found = False
                        if not (np.abs(BB[i]) < symprec).all():
                            for j in np.arange(len(CC)):
                                if (np.abs(BB[i] - CC[j]) < symprec).all():
                                    is_found = True
                                    break
                            if not is_found:
                                CC.append(BB[i])
        CC, transform, independent = gaussian(np.array(CC))
        doublet_dict['independent'] = [
            ind + index_pair * 9 for ind in independent
        ]  # independent ele
        doublet_dict['transform'] = transform
        doublets_dict.append(doublet_dict)
    num_irred = [len(dic['independent']) for dic in doublets_dict]
    trans = np.zeros((len(doublets_dict), 9, sum(num_irred)), dtype="float")
    for i, doub in enumerate(doublets_dict):
        start = sum(num_irred[:i])
        length = num_irred[i]
        trans[i, :, start:start + length] = doub['transform']
    return np.hstack((dic['independent'] for dic in doublets_dict)), trans
예제 #12
0
def get_fc3_coefficients(triplets_orig,
                         mapping_triplet,
                         transform_triplet,
                         lattice,
                         positions,
                         rotations1,
                         translations1,
                         mappings1,
                         map_ope1,
                         rotations2,
                         mappings2,
                         map_ope2,
                         rotations3,
                         mappings3,
                         map_ope3,
                         symprec,
                         first_atoms,
                         triplet=None): # returning the fc3 coefficients at a specific triplet
    natom = len(positions)
    ind_atoms1 = np.unique(mappings1)
    triplets_reduced = [triplets_orig[i] for i in np.unique(mapping_triplet)]
    if triplet is None:
        ifc_map = np.zeros((len(first_atoms), natom, natom), dtype=np.int16)
        coeff = np.zeros((len(first_atoms), natom, natom, 27, 27), dtype=np.float)
        for i, atom1 in enumerate(first_atoms):
            iratom1 = mappings1[atom1]
            numope = map_ope1[atom1]
            index1 = np.where(ind_atoms1 == iratom1)[0][0]
            ind_atoms2 = np.unique(mappings2[index1])
            rot1, tran1 = rotations1[numope], translations1[numope]
            for atom2 in np.arange(natom):
                iratom2 = get_atom_sent_by_operation(atom2, positions, rot1, tran1, symprec=symprec)
                rot2 = rotations2[index1, map_ope2[index1, iratom2]]
                iratom2 = mappings2[index1, iratom2]
                index2 = np.where(ind_atoms2 == iratom2)[0][0]
                for atom3 in np.arange(natom):
                    iratom3 = get_atom_sent_by_operation(atom3, positions, rot1, tran1, symprec=symprec)
                    iratom3 = get_atom_sent_by_site_sym(iratom3, iratom1, positions, rot2, symprec=symprec)
                    rot3 = rotations3[index1, index2, map_ope3[index1, index2, iratom3]]
                    iratom3 =mappings3[index1, index2, iratom3]
                    rot = np.dot(rot3, np.dot(rot2, rot1))
                    #rot transforms an arbitrary triplet to the irreducible one
                    index_triplet = triplets_orig.index((iratom1, iratom2, iratom3))
                    star3 = triplets_orig[mapping_triplet[index_triplet]]
                    ifc_map[i, atom2, atom3] = triplets_reduced.index(star3)
                    rot_cart = np.double(similarity_transformation(lattice, rot)).T # from irreducible to general
                    coeff_temp = np.kron(np.kron(rot_cart, rot_cart), rot_cart)
                    coeff[i, atom2, atom3] = np.dot(coeff_temp, transform_triplet[index_triplet])
                    # Considering the permutation symmetry previously obtained
    else:
        atom1, atom2, atom3 = triplet
        iratom1 = mappings1[atom1]
        numope = map_ope1[atom1]
        index1 = np.where(ind_atoms1 == iratom1)[0][0]
        ind_atoms2 = np.unique(mappings2[index1])
        rot1, tran1 = rotations1[numope], translations1[numope]
        iratom2 = get_atom_sent_by_operation(atom2, positions, rot1, tran1, symprec=symprec)
        rot2 = rotations2[index1, map_ope2[index1, iratom2]]
        iratom2 = mappings2[index1, iratom2]
        index2 = np.where(ind_atoms2 == iratom2)[0][0]
        iratom3 = get_atom_sent_by_operation(atom3, positions, rot1, tran1, symprec=symprec)
        iratom3 = get_atom_sent_by_site_sym(iratom3, iratom1, positions, rot2, symprec=symprec)
        rot3 = rotations3[index1, index2, map_ope3[index1, index2, iratom3]]
        iratom3 =mappings3[index1, index2, iratom3]
        rot = np.dot(rot3, np.dot(rot2, rot1))
        #rot transforms an arbitrary triplet to the irreducible one
        index_triplet = triplets_orig.index((iratom1, iratom2, iratom3))
        star3 = triplets_orig[mapping_triplet[index_triplet]]
        ifc_map = triplets_reduced.index(star3)
        rot_cart = np.double(similarity_transformation(lattice, rot)).T # from irreducible to general
        coeff_temp = np.kron(np.kron(rot_cart, rot_cart), rot_cart)
        coeff = np.dot(coeff_temp, transform_triplet[index_triplet])
    return coeff, ifc_map
예제 #13
0
def get_irreducible_triplets_with_permute(triplets,
                                          positions,
                                          rotations1,
                                          translations1,
                                          mappings1,
                                          mapping_opes1,
                                          rotations2,
                                          num_rotations2,
                                          mappings2,
                                          mapping_opes2,
                                          rotations3,
                                          num_rotations3,
                                          mappings3,
                                          mapping_opes3,
                                          lattice,
                                          symprec):
    triplets_mapping = np.arange(len(triplets))
    transform = np.zeros((len(triplets), 27, 27), dtype='double')
    transform[:] += np.eye(27)
    indatoms1 = np.unique(mappings1)
    for itriplet, (p1, p2, p3) in enumerate(triplets):
        triplet = (p1, p2, p3)
        # if triplet == (0, 5, 15):
        #     print "good"
        for permute in list(permutations([0,1,2]))[1:]: # Leave out the original triplet
            atom1, atom2, atom3 = [triplet[i] for i in permute] # permuted triplet
            if triplet == (atom1, atom2, atom3):
                continue
                # atom1 = triplet[permute_matrix[0]];atom2 = triplet[permute_matrix[1]]; atom3 = triplet[permute_matrix[2]] # permuted triplet
            numope = mapping_opes1[atom1] #number of symmetry operation
            rot, tran = rotations1[numope], translations1[numope]
            atom1 = mappings1[atom1]
            atom2 = get_atom_sent_by_operation(atom2, positions, rot, tran, symprec=symprec)
            atom3 = get_atom_sent_by_operation(atom3, positions, rot, tran, symprec=symprec)
            # atom1 is transformed to an independent atom and atom2 and atom3 are transformed following atom1
            index1 = np.where(indatoms1 == atom1)[0][0] # index of the first irreducible atom
            site_sym = rotations2[index1][:num_rotations2[index1]]
            mapping2 = mappings2[index1] # now atom1 would be fixed under its site symmetries
            iatoms2 = np.unique(mappings2[index1])
            rot2 = site_sym[mapping_opes2[index1,atom2]]
            # a rotation which transforms atom2 to an independent one under site symmetries
            atom2 = mapping2[atom2]
            atom3 = get_atom_sent_by_site_sym(atom3, atom1, positions, rot2, symprec=symprec)
            # atom3 is transformed following atom2
            index2 = np.where(iatoms2 == atom2)[0][0]# index of the second irreducible atom
            site_sym3 = rotations3[index1, index2, :num_rotations3[index1, index2]]
            map_ope3 = mapping_opes3[index1,index2]
            mapping3 = mappings3[index1, index2]
            rot3 = site_sym3[map_ope3[atom3]]
            atom3 = mapping3[atom3] # atom3 is also transformed to an irreducible one under bond symmetries
            triplet_permute = (atom1, atom2, atom3)
            # Check if triplet_permute already exists in the triplets pool
            permuted_index = triplets.index(triplet_permute)
            if triplets_mapping[permuted_index] < triplets_mapping[itriplet]:
                triplets_mapping[itriplet] = triplets_mapping[permuted_index]
                transf = np.dot(rot3, np.dot(rot2, rot))
                transf_cart = similarity_transformation(lattice, transf).T # Coordinate transform from  irreducible to general
                seq = "".join(['ikm'[permute.index(i)] for i in range(3)]) # find the original index before permutation
                transform_temp = np.einsum("ij, kl, mn -> %sjln" %seq, transf_cart, transf_cart, transf_cart).reshape(27, 27)
                transform[itriplet] = np.dot(transform_temp, transform[permuted_index]) # from irreducible to general
    return triplets_mapping, transform
예제 #14
0
def get_fc3_spg_invariance(triplets,
                           positions,
                           rotations1,
                           translations1,
                           mappings1,
                           rotations2,
                           num_rotations2,
                           mappings2,
                           rotations3,
                           num_rotations3,
                           mappings3,
                           lattice,
                           symprec,
                           is_disperse=False):
    "Find all spg symmetries that map the triplet to itself and thus the symmetry would act as constraints"
    triplets_dict = []
    iatoms1 = np.unique(mappings1)
    for itriplet, triplet in enumerate(triplets):
        triplet_dict = {}
        triplet_dict["triplet"] = triplet
        CC = [np.zeros(27)]

        for permute in list(permutations([0,1,2])): # Leave out the original triplet
            rot_all = []
            atom1, atom2, atom3 = [triplet[i] for i in permute]
            if not mappings1[atom1] == triplet[0]:
                continue
            for numope in get_all_operations_at_star(rotations1,
                                                     translations1,
                                                     positions,
                                                     atom1,
                                                     mappings1,
                                                     symprec):
                #get all the symmetry operations that keep atom1 unchanged
                rot1, tran = rotations1[numope], translations1[numope]
                atom1_1 = mappings1[atom1]
                index1 = np.where(iatoms1 == atom1_1)[0][0] # index of the first irreducible atom
                atom2_1 = get_atom_sent_by_operation(atom2, positions, rot1, tran, symprec=symprec)
                atom3_1 = get_atom_sent_by_operation(atom3, positions, rot1, tran, symprec=symprec)
                site_syms = rotations2[index1, :num_rotations2[index1]]
                mapping2 = mappings2[index1] # now atom1 would be fixed under its site symmetries
                iatoms2 = np.unique(mapping2)
                if mapping2[atom2_1] != triplet[1]:
                    continue
                for rot2 in get_rotations_at_star(site_syms, positions, atom1_1, atom2_1, mapping2, symprec):
                    #get all the symmetry operations that keep both atom1 and atom2 unchanged
                    atom2_2 = mapping2[atom2_1]
                    atom3_2 = get_atom_sent_by_site_sym(atom3_1, atom1_1, positions, rot2, symprec=symprec) #no matter atom1_1 or atom2_1
                    index2 = np.where(iatoms2 == atom2_2)[0][0]# index of the second irreducible atom
                    site_syms3 = rotations3[index1, index2, :num_rotations3[index1, index2]]
                    mapping3 = mappings3[index1, index2]
                    if not mapping3[atom3_2] == triplet[2]:
                        continue
                    for rot3 in get_rotations_at_star(site_syms3, positions, atom2_2, atom3_2, mapping3, symprec):
                        rot = np.dot(rot3, np.dot(rot2, rot1))
                        isfound = False
                        for r in rot_all:
                            if (np.abs(r-rot) < symprec).all():
                                isfound = True
                                break
                        if not isfound:
                            rot_all.append(rot)
                        else:
                            continue
                        # rot_cart = np.double(similarity_transformation(lattice, rot))
                        # seq = "".join(["ikm"[i] for i in permute])
                        # PP  = np.einsum("ij,kl,mn -> %sjln"%seq, rot_cart, rot_cart, rot_cart).reshape(27, 27).T

                        rot_cart = np.double(similarity_transformation(lattice, rot)).T
                        seq = "".join(['ikm'[permute.index(i)] for i in range(3)]) # find the original index before permutation
                        PP = np.einsum("ij,kl,mn -> %sjln"%seq, rot_cart, rot_cart, rot_cart).reshape(27, 27)
                        BB = PP - np.eye(27)
                        for i in np.arange(27):
                            is_found = False
                            if not (np.abs(BB[i]) < symprec).all():
                                row = BB[i] / np.abs(BB[i]).max()
                                for j in np.arange(len(CC)):
                                    if (np.abs(row - CC[j]) < symprec).all():
                                        is_found = True
                                        break
                                if not is_found:
                                    CC.append(row)
        DD = np.array(CC, dtype='double')
        CC, transform, independent = gaussian(DD)
        triplet_dict['independent'] = [ind + itriplet * 27 for ind in independent] # independent ele
        triplet_dict['transform'] = transform
        triplets_dict.append(triplet_dict)
    num_irred = [len(dic['independent']) for dic in triplets_dict]
    ind_elements = np.hstack((dic['independent'] for dic in triplets_dict))
    if is_disperse:
        from scipy.sparse import coo_matrix
        trans = []
        for i, trip in enumerate(triplets_dict):
            start = sum(num_irred[:i])
            length = num_irred[i]
            transform_tmp = np.zeros((27, sum(num_irred)), dtype="float")
            transform_tmp[:, start:start + length] = trip['transform']
            non_zero = np.where(np.abs(transform_tmp) > symprec)
            transform_tmp_sparse = coo_matrix((transform_tmp[non_zero], non_zero), shape=transform_tmp.shape)
            trans.append(transform_tmp_sparse)
    else:
        trans = np.zeros((len(triplets_dict), 27, sum(num_irred)), dtype="float")
        for i, trip in enumerate(triplets_dict):
            start = sum(num_irred[:i])

            length = num_irred[i]
            trans[i,:, start:start + length] = trip['transform']
    return ind_elements, trans