def _distribute_forces(supercell, disp, forces, filename, symprec): natom = supercell.get_number_of_atoms() lattice = supercell.get_cell() symbols = supercell.get_chemical_symbols() positions = supercell.get_positions() positions[disp[0]] += disp[1] cell = Atoms(cell=lattice, positions=positions, symbols=symbols, pbc=True) symmetry = Symmetry(cell, symprec) independent_atoms = symmetry.get_independent_atoms() # Rotation matrices in Cartesian rotations = [] for r in symmetry.get_symmetry_operations()["rotations"]: rotations.append(similarity_transformation(lattice.T, r)) map_operations = symmetry.get_map_operations() map_atoms = symmetry.get_map_atoms() atoms_in_dot_scf = _get_independent_atoms_in_dot_scf(filename) if len(forces) != len(atoms_in_dot_scf): print("%s does not contain necessary information." % filename) print('Plese check if there are "FGL" lines with') print('"total forces" are required.') return False if len(atoms_in_dot_scf) == natom: print("It is assumed that there is no symmetrically-equivalent " "atoms in ") print("'%s' at wien2k calculation." % filename) force_set = forces elif len(forces) != len(independent_atoms): print("Non-equivalent atoms of %s could not be recognized by phonopy." % filename) return False else: # 1. Transform wien2k forces to those on independent atoms indep_atoms_to_wien2k = [] forces_remap = [] for i, pos_wien2k in enumerate(atoms_in_dot_scf): for j, pos in enumerate(cell.get_scaled_positions()): diff = pos_wien2k - pos diff -= np.rint(diff) if (abs(diff) < symprec).all(): forces_remap.append(np.dot(rotations[map_operations[j]], forces[i])) indep_atoms_to_wien2k.append(map_atoms[j]) break if len(forces_remap) != len(forces): print("Atomic position mapping between Wien2k and phonopy failed.") print("If you think this is caused by a bug of phonopy") print("please report it in the phonopy mainling list.") return False # 2. Distribute forces from independent to dependent atoms. force_set = [] for i in range(natom): j = indep_atoms_to_wien2k.index(map_atoms[i]) force_set.append(np.dot(rotations[map_operations[i]].T, forces_remap[j])) return force_set
def get_cell_from_phonopy_structure(ph_structure: PhonopyAtoms, use_atomic_number: bool = False) -> tuple: """ Get cell from phonopy structure Args: ph_structure: PhonopyAtoms object use_atomic_number: if True, use atomic number intead of atomic symbol Returns: tuple: (lattice, scaled_positions, symbols). """ lattice = ph_structure.get_cell() scaled_positions = ph_structure.get_scaled_positions() if use_atomic_number: elements = list(ph_structure.get_atomic_numbers()) else: elements = ph_structure.get_chemical_symbols() return (lattice, scaled_positions, elements)
def _distribute_forces(supercell, disp, forces, filename, symprec): natom = supercell.get_number_of_atoms() lattice = supercell.get_cell() symbols = supercell.get_chemical_symbols() positions = supercell.get_positions() positions[disp[0]] += disp[1] cell = Atoms(cell=lattice, positions=positions, symbols=symbols, pbc=True) symmetry = Symmetry(cell, symprec) independent_atoms = symmetry.get_independent_atoms() # Rotation matrices in Cartesian rotations = [] for r in symmetry.get_symmetry_operations()['rotations']: rotations.append(similarity_transformation(lattice.T, r)) map_operations = symmetry.get_map_operations() map_atoms = symmetry.get_map_atoms() atoms_in_dot_scf = _get_independent_atoms_in_dot_scf(filename) if len(forces) != len(atoms_in_dot_scf): print("%s does not contain necessary information." % filename) print("Plese check if there are \"FGL\" lines with") print("\"total forces\" are required.") return False if len(atoms_in_dot_scf) == natom: print("It is assumed that there is no symmetrically-equivalent " "atoms in ") print("\'%s\' at wien2k calculation." % filename) force_set = forces elif len(forces) != len(independent_atoms): print( "Non-equivalent atoms of %s could not be recognized by phonopy." % filename) return False else: # 1. Transform wien2k forces to those on independent atoms indep_atoms_to_wien2k = [] forces_remap = [] for i, pos_wien2k in enumerate(atoms_in_dot_scf): for j, pos in enumerate(cell.get_scaled_positions()): diff = pos_wien2k - pos diff -= np.rint(diff) if (abs(diff) < symprec).all(): forces_remap.append( np.dot(rotations[map_operations[j]], forces[i])) indep_atoms_to_wien2k.append(map_atoms[j]) break if len(forces_remap) != len(forces): print("Atomic position mapping between Wien2k and phonopy failed.") print("If you think this is caused by a bug of phonopy") print("please report it in the phonopy mainling list.") return False # 2. Distribute forces from independent to dependent atoms. force_set = [] for i in range(natom): j = indep_atoms_to_wien2k.index(map_atoms[i]) force_set.append( np.dot(rotations[map_operations[i]].T, forces_remap[j])) return force_set
def assert_same_phonopy_atoms(actual: PhonopyAtoms, expected: PhonopyAtoms): assert (actual.get_cell() == expected.get_cell()).all() assert (actual.get_scaled_positions() == expected.get_scaled_positions() ).all() assert actual.symbols == expected.symbols