def _expand_fc2(fc2_alm, supercell, pure_trans, rotations, symprec=1e-5, verbose=True): natom = supercell.get_number_of_atoms() fc2 = np.zeros((natom, natom, 3, 3), dtype='double', order='C') (fc_values, elem_indices) = fc2_alm first_atoms = np.unique(elem_indices[:, 0] // 3) for (fc, indices) in zip(fc_values, elem_indices): v1 = indices[0] // 3 c1 = indices[0] % 3 v2 = indices[1] // 3 c2 = indices[1] % 3 fc2[v1, v2, c1, c2] = fc lattice = np.array(supercell.get_cell().T, dtype='double', order='C') positions = supercell.get_scaled_positions() permutations = compute_all_sg_permutations(positions, rotations, pure_trans, lattice, symprec) distribute_force_constants(fc2, first_atoms, lattice, rotations, permutations) return fc2
def run_phonon_solver_with_eigvec_rotation(self): """Phonons at ir-grid-points are copied by proper rotations. Some phonons that are not covered by rotations are solved. The following data are updated. self._frequencies self._eigenvectors self._phonon_done """ self._phonon_done[:] = 0 ir_grid_points, _, _ = get_ir_grid_points(self._bz_grid) ir_bz_grid_points = self._bz_grid.grg2bzg[ir_grid_points] self.run_phonon_solver(grid_points=ir_bz_grid_points) d2r_map = self._get_reciprocal_rotations_in_space_group_operations() # perms.shape = (len(spg_ops), len(primitive)), dtype='intc' perms = compute_all_sg_permutations( self._primitive.scaled_positions, self._bz_grid.symmetry_dataset["rotations"], self._bz_grid.symmetry_dataset["translations"], np.array(self._primitive.cell.T, dtype="double", order="C"), symprec=self._symprec, ) for d_i, r_i in enumerate(d2r_map): r = self._bz_grid.rotations[r_i] r_cart = self._bz_grid.rotations_cartesian[r_i] for irgp in ir_bz_grid_points: bzgp = get_grid_points_by_rotations( irgp, self._bz_grid, reciprocal_rotations=[ r, ], with_surface=True, )[0] if self._phonon_done[bzgp]: continue self._rotate_eigvecs(irgp, bzgp, r_cart, perms[d_i], d_i) bz_grid_points_solved = self._get_phonons_at_minus_q() if bz_grid_points_solved: print("DEBUG: BZ-grid points additionally solved " "than ir-grid-points.") qpoints = np.dot( self._bz_grid.addresses[bz_grid_points_solved] / self._bz_grid.D_diag.astype("double"), self._bz_grid.Q.T, ) distances = np.linalg.norm(np.dot( qpoints, np.linalg.inv(self._primitive.cell).T), axis=1) for qpt, dist in zip(qpoints, distances): print(qpt, dist)
def get_constrained_fc2(supercell, dataset_second_atoms, atom1, forces1, reduced_site_sym, symprec): """ dataset_second_atoms: [{'number': 7, 'displacement': [], 'forces': []}, ...] """ lattice = supercell.get_cell().T positions = supercell.get_scaled_positions() num_atom = supercell.get_number_of_atoms() fc2 = np.zeros((num_atom, num_atom, 3, 3), dtype='double') atom_list = np.unique([x['number'] for x in dataset_second_atoms]) for atom2 in atom_list: disps2 = [] sets_of_forces = [] for disps_second in dataset_second_atoms: if atom2 != disps_second['number']: continue bond_sym = get_bond_symmetry( reduced_site_sym, lattice, positions, atom1, atom2, symprec) disps2.append(disps_second['displacement']) sets_of_forces.append(disps_second['forces'] - forces1) solve_force_constants(fc2, atom2, disps2, sets_of_forces, supercell, bond_sym, symprec) # Shift positions according to set atom1 is at origin pos_center = positions[atom1].copy() positions -= pos_center rotations = np.array(reduced_site_sym, dtype='intc', order='C') translations = np.zeros((len(reduced_site_sym), 3), dtype='double', order='C') permutations = compute_all_sg_permutations(positions, rotations, translations, lattice, symprec) distribute_force_constants(fc2, atom_list, lattice, rotations, permutations) return fc2
def _set_atomic_permutations(self): positions = self._cell.scaled_positions lattice = np.array(self._cell.cell.T, dtype='double', order='C') rotations = self._symmetry_operations['rotations'] translations = self._symmetry_operations['translations'] self._atomic_permutations = compute_all_sg_permutations( positions, # scaled positions rotations, # scaled translations, # scaled lattice, # column vectors self._symprec)
def _set_atomic_permutations(self): positions = self._cell.scaled_positions lattice = np.array(self._cell.cell.T, dtype="double", order="C") rotations = self._symmetry_operations["rotations"] translations = self._symmetry_operations["translations"] self._atomic_permutations = compute_all_sg_permutations( positions, # scaled positions rotations, # scaled translations, # scaled lattice, # column vectors self._symprec, )
def get_atomic_permutations(self): if self._atomic_permutations is None: positions = self._cell.get_scaled_positions() lattice = np.array(self._cell.get_cell().T, dtype='double', order='C') rotations = self._symmetry_operations['rotations'] translations = self._symmetry_operations['translations'] self._atomic_permutations = compute_all_sg_permutations( positions, # scaled positions rotations, # scaled translations, # scaled lattice, # column vectors self._symprec) return self._atomic_permutations
def _test_compute_permutation(ph: Phonopy): symmetry = ph.primitive_symmetry ppos = ph.primitive.scaled_positions plat = ph.primitive.cell.T symprec = symmetry.tolerance rots = symmetry.symmetry_operations["rotations"] trans = symmetry.symmetry_operations["translations"] perms = compute_all_sg_permutations(ppos, rots, trans, plat, symprec) for i, (r, t) in enumerate(zip(rots, trans)): ppos_rot = np.dot(ppos, r.T) + t perm = compute_permutation_for_rotation(ppos, ppos_rot, plat, symprec) np.testing.assert_array_equal(perms[i], perm) diff = ppos[perm] - ppos_rot diff -= np.rint(diff) assert ((np.dot(diff, plat)**2).sum(axis=1) < symprec).all()
def _get_constrained_fc2(supercell, dataset_second_atoms, atom1, forces1, reduced_site_sym, symprec): """Return fc2 under reduced (broken) site symmetry by first displacement. dataset_second_atoms: [{'number': 7, 'displacement': [], 'forces': []}, ...] """ lattice = supercell.cell.T positions = supercell.scaled_positions num_atom = len(supercell) fc2 = np.zeros((num_atom, num_atom, 3, 3), dtype="double") atom_list = np.unique([x["number"] for x in dataset_second_atoms]) for atom2 in atom_list: disps2 = [] sets_of_forces = [] for disps_second in dataset_second_atoms: if atom2 != disps_second["number"]: continue bond_sym = get_bond_symmetry(reduced_site_sym, lattice, positions, atom1, atom2, symprec) disps2.append(disps_second["displacement"]) sets_of_forces.append(disps_second["forces"] - forces1) solve_force_constants(fc2, atom2, disps2, sets_of_forces, supercell, bond_sym, symprec) # Shift positions according to set atom1 is at origin pos_center = positions[atom1].copy() positions -= pos_center rotations = np.array(reduced_site_sym, dtype="intc", order="C") translations = np.zeros((len(reduced_site_sym), 3), dtype="double", order="C") permutations = compute_all_sg_permutations(positions, rotations, translations, lattice, symprec) distribute_force_constants(fc2, atom_list, lattice, rotations, permutations) return fc2
def _expand_fc3(fc3_alm, supercell, pure_trans, rotations, symprec=1e-5, verbose=True): (fc_values, elem_indices) = fc3_alm natom = supercell.get_number_of_atoms() fc3 = np.zeros((natom, natom, natom, 3, 3, 3), dtype='double', order='C') first_atoms = np.unique(elem_indices[:, 0] // 3) for (fc, indices) in zip(fc_values, elem_indices): v1, v2, v3 = indices // 3 c1, c2, c3 = indices % 3 fc3[v1, v2, v3, c1, c2, c3] = fc fc3[v1, v3, v2, c1, c3, c2] = fc lattice = np.array(supercell.get_cell().T, dtype='double', order='C') positions = supercell.get_scaled_positions() s2compact = np.arange(supercell.get_number_of_atoms(), dtype='intc') target_atoms = [i for i in s2compact if i not in first_atoms] permutations = compute_all_sg_permutations(positions, rotations, pure_trans, lattice, symprec) if verbose: print("Expanding fc3") distribute_fc3(fc3, first_atoms, target_atoms, lattice, rotations, permutations, s2compact, verbose=verbose) return fc3