예제 #1
0
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
예제 #2
0
    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)
예제 #3
0
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
예제 #4
0
 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)
예제 #5
0
 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,
     )
예제 #6
0
파일: symmetry.py 프로젝트: atztogo/phonopy
    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
예제 #7
0
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()
예제 #8
0
파일: fc3.py 프로젝트: phonopy/phono3py
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
예제 #9
0
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