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
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
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
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
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
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
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
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
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
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
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
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
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
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