Exemple #1
0
class MeshBase(object):
    def __init__(
            self,
            dynamical_matrix,
            mesh,
            shift=None,
            is_time_reversal=True,
            is_mesh_symmetry=True,
            is_eigenvectors=False,
            is_gamma_center=False,
            rotations=None,  # Point group operations in real space
            factor=VaspToTHz):
        self._mesh = np.array(mesh, dtype='intc')
        self._is_eigenvectors = is_eigenvectors
        self._factor = factor
        self._cell = dynamical_matrix.get_primitive()
        self._dynamical_matrix = dynamical_matrix

        self._gp = GridPoints(self._mesh,
                              np.linalg.inv(self._cell.get_cell()),
                              q_mesh_shift=shift,
                              is_gamma_center=is_gamma_center,
                              is_time_reversal=(is_time_reversal
                                                and is_mesh_symmetry),
                              rotations=rotations,
                              is_mesh_symmetry=is_mesh_symmetry)

        self._qpoints = self._gp.get_ir_qpoints()
        self._weights = self._gp.get_ir_grid_weights()

        self._frequencies = None
        self._eigenvalues = None
        self._eigenvectors = None

    def get_dynamical_matrix(self):
        return self._dynamical_matrix

    def get_mesh_numbers(self):
        return self._mesh

    def get_qpoints(self):
        return self._qpoints

    def get_weights(self):
        return self._weights

    def get_grid_address(self):
        return self._gp.get_grid_address()

    def get_ir_grid_points(self):
        return self._gp.get_ir_grid_points()

    def get_grid_mapping_table(self):
        return self._gp.get_grid_mapping_table()

    def get_eigenvalues(self):
        return self._eigenvalues

    def get_frequencies(self):
        return self._frequencies
Exemple #2
0
 def testGridPoints(self):
     gp = GridPoints([11, 11, 11], [[-1, 1, 1], [1, -1, 1], [1, 1, -1]])
     self.assertTrue((gp.grid_address == gp.get_grid_address()).all())
     self.assertTrue((gp.ir_grid_points == gp.get_ir_grid_points()).all())
     np.testing.assert_allclose(gp.qpoints, gp.get_ir_qpoints())
     self.assertTrue((gp.weights == gp.get_ir_grid_weights()).all())
     self.assertTrue(
         (gp.grid_mapping_table == gp.get_grid_mapping_table()).all())
Exemple #3
0
 def testGridPoints(self):
     gp = GridPoints([11, 11, 11],
                     [[-1, 1, 1], [1, -1, 1], [1, 1, -1]])
     self.assertTrue((gp.grid_address == gp.get_grid_address()).all())
     self.assertTrue((gp.ir_grid_points == gp.get_ir_grid_points()).all())
     np.testing.assert_allclose(gp.qpoints, gp.get_ir_qpoints())
     self.assertTrue((gp.weights == gp.get_ir_grid_weights()).all())
     self.assertTrue((gp.grid_mapping_table ==
                      gp.get_grid_mapping_table()).all())
Exemple #4
0
class Mesh:
    def __init__(self,
                 dynamical_matrix,
                 mesh,
                 shift=None,
                 is_time_reversal=True,
                 is_mesh_symmetry=True,
                 is_eigenvectors=False,
                 is_gamma_center=False,
                 group_velocity=None,
                 rotations=None, # Point group operations in real space
                 factor=VaspToTHz):
        self._mesh = np.array(mesh, dtype='intc')
        self._is_eigenvectors = is_eigenvectors
        self._factor = factor
        self._cell = dynamical_matrix.get_primitive()
        self._dynamical_matrix = dynamical_matrix

        self._gp = GridPoints(self._mesh,
                              np.linalg.inv(self._cell.get_cell()),
                              q_mesh_shift=shift,
                              is_gamma_center=is_gamma_center,
                              is_time_reversal=is_time_reversal,
                              rotations=rotations,
                              is_mesh_symmetry=is_mesh_symmetry)
        self._qpoints = self._gp.get_ir_qpoints()
        self._weights = self._gp.get_ir_grid_weights()

        self._frequencies = None
        self._eigenvalues = None
        self._eigenvectors = None
        self._set_phonon()

        self._group_velocities = None
        if group_velocity is not None:
            self._set_group_velocities(group_velocity)

    def get_dynamical_matrix(self):
        return self._dynamical_matrix
        
    def get_mesh_numbers(self):
        return self._mesh
        
    def get_qpoints(self):
        return self._qpoints

    def get_weights(self):
        return self._weights

    def get_grid_address(self):
        return self._gp.get_grid_address()

    def get_ir_grid_points(self):
        return self._gp.get_ir_grid_points()
    
    def get_grid_mapping_table(self):
        return self._gp.get_grid_mapping_table()

    def get_eigenvalues(self):
        return self._eigenvalues

    def get_frequencies(self):
        return self._frequencies

    def get_group_velocities(self):
        return self._group_velocities
    
    def get_eigenvectors(self):
        """
        Eigenvectors is a numpy array of three dimension.
        The first index runs through q-points.
        In the second and third indices, eigenvectors obtained
        using numpy.linalg.eigh are stored.
        
        The third index corresponds to the eigenvalue's index.
        The second index is for atoms [x1, y1, z1, x2, y2, z2, ...].
        """
        return self._eigenvectors


    def write_yaml(self):
        w = open('mesh.yaml', 'w')
        eigenvalues = self._eigenvalues
        natom = self._cell.get_number_of_atoms()
        lattice = np.linalg.inv(self._cell.get_cell()) # column vectors
        w.write("mesh: [ %5d, %5d, %5d ]\n" % tuple(self._mesh))
        w.write("nqpoint: %-7d\n" % self._qpoints.shape[0])
        w.write("natom:   %-7d\n" % natom)
        w.write("reciprocal_lattice:\n")
        for vec, axis in zip(lattice.T, ('a*', 'b*', 'c*')):
            w.write("- [ %12.8f, %12.8f, %12.8f ] # %2s\n" %
                    (tuple(vec) + (axis,)))
        w.write("phonon:\n")

        for i, q in enumerate(self._qpoints):
            w.write("- q-position: [ %12.7f, %12.7f, %12.7f ]\n" % tuple(q))
            w.write("  weight: %-5d\n" % self._weights[i])
            w.write("  band:\n")

            for j, eig in enumerate(eigenvalues[i]):
                w.write("  - # %d\n" % (j+1))
                if eig < 0:
                    freq = -np.sqrt(-eig)
                else:
                    freq = np.sqrt(eig)
                w.write("    frequency:  %15.10f\n" % (freq * self._factor))

                if self._group_velocities is not None:
                    w.write("    group_velocity: ")
                    w.write("[ %13.7f, %13.7f, %13.7f ]\n" %
                            tuple(self._group_velocities[i, j]))

                if self._is_eigenvectors:
                    w.write("    eigenvector:\n")
                    for k in range(natom):
                        w.write("    - # atom %d\n" % (k+1))
                        for l in (0,1,2):
                            w.write("      - [ %17.14f, %17.14f ]\n" %
                                    (self._eigenvectors[i,k*3+l,j].real,
                                     self._eigenvectors[i,k*3+l,j].imag))
            w.write("\n")

    def _set_phonon(self):
        num_band = self._cell.get_number_of_atoms() * 3
        num_qpoints = len(self._qpoints)

        self._eigenvalues = np.zeros((num_qpoints, num_band), dtype='double')
        self._frequencies = np.zeros_like(self._eigenvalues)
        if self._is_eigenvectors:
            self._eigenvectors = np.zeros(
                (num_qpoints, num_band, num_band,), dtype='complex128')
            
        for i, q in enumerate(self._qpoints):
            self._dynamical_matrix.set_dynamical_matrix(q)
            dm = self._dynamical_matrix.get_dynamical_matrix()
            if self._is_eigenvectors:
                eigvals, self._eigenvectors[i] = np.linalg.eigh(dm)
                self._eigenvalues[i] = eigvals.real
            else:
                self._eigenvalues[i] = np.linalg.eigvalsh(dm).real

        self._frequencies = np.array(np.sqrt(abs(self._eigenvalues)) *
                                     np.sign(self._eigenvalues)) * self._factor

    def _set_group_velocities(self, group_velocity):
        group_velocity.set_q_points(self._qpoints)
        self._group_velocities = group_velocity.get_group_velocity()
Exemple #5
0
class Mesh:
    def __init__(self,
                 dynamical_matrix,
                 mesh,
                 shift=None,
                 is_time_reversal=True,
                 is_mesh_symmetry=True,
                 is_eigenvectors=False,
                 is_gamma_center=False,
                 group_velocity=None,
                 rotations=None, # Point group operations in real space
                 factor=VaspToTHz,
                 use_lapack_solver=False):

        self._mesh = np.array(mesh, dtype='intc')
        self._is_eigenvectors = is_eigenvectors
        self._factor = factor
        self._cell = dynamical_matrix.get_primitive()
        self._dynamical_matrix = dynamical_matrix
        self._use_lapack_solver = use_lapack_solver

        self._gp = GridPoints(self._mesh,
                              np.linalg.inv(self._cell.get_cell()),
                              q_mesh_shift=shift,
                              is_gamma_center=is_gamma_center,
                              is_time_reversal=is_time_reversal,
                              rotations=rotations,
                              is_mesh_symmetry=is_mesh_symmetry)

        self._qpoints = self._gp.get_ir_qpoints()
        self._weights = self._gp.get_ir_grid_weights()

        self._frequencies = None
        self._eigenvalues = None
        self._eigenvectors = None
        self._set_phonon()

        self._group_velocities = None
        if group_velocity is not None:
            self._set_group_velocities(group_velocity)

    def get_dynamical_matrix(self):
        return self._dynamical_matrix
        
    def get_mesh_numbers(self):
        return self._mesh
        
    def get_qpoints(self):
        return self._qpoints

    def get_weights(self):
        return self._weights

    def get_grid_address(self):
        return self._gp.get_grid_address()

    def get_ir_grid_points(self):
        return self._gp.get_ir_grid_points()
    
    def get_grid_mapping_table(self):
        return self._gp.get_grid_mapping_table()

    def get_eigenvalues(self):
        return self._eigenvalues

    def get_frequencies(self):
        return self._frequencies

    def get_group_velocities(self):
        return self._group_velocities
    
    def get_eigenvectors(self):
        """
        Eigenvectors is a numpy array of three dimension.
        The first index runs through q-points.
        In the second and third indices, eigenvectors obtained
        using numpy.linalg.eigh are stored.
        
        The third index corresponds to the eigenvalue's index.
        The second index is for atoms [x1, y1, z1, x2, y2, z2, ...].
        """
        return self._eigenvectors

    def write_hdf5(self):
        import h5py
        with h5py.File('mesh.hdf5', 'w') as w:
            w.create_dataset('mesh', data=self._mesh)
            w.create_dataset('qpoint', data=self._qpoints)
            w.create_dataset('weight', data=self._weights)
            w.create_dataset('frequency', data=self._frequencies)
            if self._eigenvectors is not None:
                w.create_dataset('eigenvector', data=self._eigenvectors)
            if self._group_velocities is not None:
                w.create_dataset('group_velocity', data=self._group_velocities)

    def write_yaml(self):
        w = open('mesh.yaml', 'w')
        eigenvalues = self._eigenvalues
        natom = self._cell.get_number_of_atoms()
        rec_lattice = np.linalg.inv(self._cell.get_cell()) # column vectors
        supercell = self._dynamical_matrix.get_supercell()
        smat = supercell.get_supercell_matrix()
        pmat = self._cell.get_primitive_matrix()
        tmat = np.rint(np.dot(np.linalg.inv(pmat), smat)).astype(int)


        w.write("mesh: [ %5d, %5d, %5d ]\n" % tuple(self._mesh))
        w.write("nqpoint: %-7d\n" % self._qpoints.shape[0])
        w.write("reciprocal_lattice:\n")
        for vec, axis in zip(rec_lattice.T, ('a*', 'b*', 'c*')):
            w.write("- [ %12.8f, %12.8f, %12.8f ] # %2s\n" %
                    (tuple(vec) + (axis,)))
        w.write("natom:   %-7d\n" % natom)
        w.write(str(PhonopyAtoms(atoms=self._cell)))
        w.write("\n")
        w.write("supercell_matrix:\n")
        for v in tmat:
            w.write("- [ %4d, %4d, %4d ]\n" % tuple(v))

        w.write("\n")
        w.write("phonon:\n")

        for i, q in enumerate(self._qpoints):
            w.write("- q-position: [ %12.7f, %12.7f, %12.7f ]\n" % tuple(q))
            w.write("  weight: %-5d\n" % self._weights[i])
            w.write("  band:\n")

            for j, freq in enumerate(self._frequencies[i]):
                w.write("  - # %d\n" % (j + 1))
                w.write("    frequency:  %15.10f\n" % freq)

                if self._group_velocities is not None:
                    w.write("    group_velocity: ")
                    w.write("[ %13.7f, %13.7f, %13.7f ]\n" %
                            tuple(self._group_velocities[i, j]))

                if self._is_eigenvectors:
                    w.write("    eigenvector:\n")
                    for k in range(natom):
                        w.write("    - # atom %d\n" % (k+1))
                        for l in (0,1,2):
                            w.write("      - [ %17.14f, %17.14f ]\n" %
                                    (self._eigenvectors[i,k*3+l,j].real,
                                     self._eigenvectors[i,k*3+l,j].imag))
            w.write("\n")

    def _set_phonon(self):
        num_band = self._cell.get_number_of_atoms() * 3
        num_qpoints = len(self._qpoints)

        self._eigenvalues = np.zeros((num_qpoints, num_band), dtype='double')
        self._frequencies = np.zeros_like(self._eigenvalues)
        if self._is_eigenvectors or self._use_lapack_solver:
            self._eigenvectors = np.zeros(
                (num_qpoints, num_band, num_band,), dtype='complex128')

        if self._use_lapack_solver:
            from phonopy.phonon.solver import get_phonons_at_qpoints
            get_phonons_at_qpoints(self._frequencies,
                                   self._eigenvectors,
                                   self._dynamical_matrix,
                                   self._qpoints,
                                   self._factor,
                                   nac_q_direction=None,
                                   lapack_zheev_uplo='L')
            self._eigenvalues = np.array(self._frequencies ** 2 *
                                         np.sign(self._frequencies),
                                         dtype='double',
                                         order='C') / self._factor ** 2
            if not self._is_eigenvectors:
                self._eigenvalues = None
        else:
            for i, q in enumerate(self._qpoints):
                self._dynamical_matrix.set_dynamical_matrix(q)
                dm = self._dynamical_matrix.get_dynamical_matrix()
                if self._is_eigenvectors:
                    eigvals, self._eigenvectors[i] = np.linalg.eigh(dm)
                    self._eigenvalues[i] = eigvals.real
                else:
                    self._eigenvalues[i] = np.linalg.eigvalsh(dm).real
            self._frequencies = np.array(np.sqrt(abs(self._eigenvalues)) *
                                         np.sign(self._eigenvalues),
                                         dtype='double',
                                         order='C') * self._factor


    def _set_group_velocities(self, group_velocity):
        group_velocity.set_q_points(self._qpoints)
        self._group_velocities = group_velocity.get_group_velocity()
Exemple #6
0
class Mesh:
    def __init__(
            self,
            dynamical_matrix,
            mesh,
            shift=None,
            is_time_reversal=True,
            is_mesh_symmetry=True,
            is_eigenvectors=False,
            is_gamma_center=False,
            group_velocity=None,
            rotations=None,  # Point group operations in real space
            factor=VaspToTHz):
        self._mesh = np.array(mesh, dtype='intc')
        self._is_eigenvectors = is_eigenvectors
        self._factor = factor
        self._cell = dynamical_matrix.get_primitive()
        self._dynamical_matrix = dynamical_matrix

        self._gp = GridPoints(self._mesh,
                              np.linalg.inv(self._cell.get_cell()),
                              q_mesh_shift=shift,
                              is_gamma_center=is_gamma_center,
                              is_time_reversal=is_time_reversal,
                              rotations=rotations,
                              is_mesh_symmetry=is_mesh_symmetry)
        self._qpoints = self._gp.get_ir_qpoints()
        self._weights = self._gp.get_ir_grid_weights()

        self._frequencies = None
        self._eigenvalues = None
        self._eigenvectors = None
        self._set_phonon()

        self._group_velocities = None
        if group_velocity is not None:
            self._set_group_velocities(group_velocity)

    def get_dynamical_matrix(self):
        return self._dynamical_matrix

    def get_mesh_numbers(self):
        return self._mesh

    def get_qpoints(self):
        return self._qpoints

    def get_weights(self):
        return self._weights

    def get_grid_address(self):
        return self._gp.get_grid_address()

    def get_ir_grid_points(self):
        return self._gp.get_ir_grid_points()

    def get_grid_mapping_table(self):
        return self._gp.get_grid_mapping_table()

    def get_eigenvalues(self):
        return self._eigenvalues

    def get_frequencies(self):
        return self._frequencies

    def get_group_velocities(self):
        return self._group_velocities

    def get_eigenvectors(self):
        """
        Eigenvectors is a numpy array of three dimension.
        The first index runs through q-points.
        In the second and third indices, eigenvectors obtained
        using numpy.linalg.eigh are stored.
        
        The third index corresponds to the eigenvalue's index.
        The second index is for atoms [x1, y1, z1, x2, y2, z2, ...].
        """
        return self._eigenvectors

    def write_yaml(self):
        w = open('mesh.yaml', 'w')
        eigenvalues = self._eigenvalues
        natom = self._cell.get_number_of_atoms()
        lattice = np.linalg.inv(self._cell.get_cell())  # column vectors
        w.write("mesh: [ %5d, %5d, %5d ]\n" % tuple(self._mesh))
        w.write("nqpoint: %-7d\n" % self._qpoints.shape[0])
        w.write("natom:   %-7d\n" % natom)
        w.write("reciprocal_lattice:\n")
        for vec, axis in zip(lattice.T, ('a*', 'b*', 'c*')):
            w.write("- [ %12.8f, %12.8f, %12.8f ] # %2s\n" % (tuple(vec) +
                                                              (axis, )))
        w.write("phonon:\n")

        for i, q in enumerate(self._qpoints):
            w.write("- q-position: [ %12.7f, %12.7f, %12.7f ]\n" % tuple(q))
            w.write("  weight: %-5d\n" % self._weights[i])
            w.write("  band:\n")

            for j, eig in enumerate(eigenvalues[i]):
                w.write("  - # %d\n" % (j + 1))
                if eig < 0:
                    freq = -np.sqrt(-eig)
                else:
                    freq = np.sqrt(eig)
                w.write("    frequency:  %15.10f\n" % (freq * self._factor))

                if self._group_velocities is not None:
                    w.write("    group_velocity: ")
                    w.write("[ %13.7f, %13.7f, %13.7f ]\n" %
                            tuple(self._group_velocities[i, j]))

                if self._is_eigenvectors:
                    w.write("    eigenvector:\n")
                    for k in range(natom):
                        w.write("    - # atom %d\n" % (k + 1))
                        for l in (0, 1, 2):
                            w.write("      - [ %17.14f, %17.14f ]\n" %
                                    (self._eigenvectors[i, k * 3 + l, j].real,
                                     self._eigenvectors[i, k * 3 + l, j].imag))
            w.write("\n")

    def _set_phonon(self):
        num_band = self._cell.get_number_of_atoms() * 3
        num_qpoints = len(self._qpoints)

        self._eigenvalues = np.zeros((num_qpoints, num_band), dtype='double')
        self._frequencies = np.zeros_like(self._eigenvalues)
        if self._is_eigenvectors:
            self._eigenvectors = np.zeros((
                num_qpoints,
                num_band,
                num_band,
            ),
                                          dtype='complex128')

        for i, q in enumerate(self._qpoints):
            self._dynamical_matrix.set_dynamical_matrix(q)
            dm = self._dynamical_matrix.get_dynamical_matrix()
            if self._is_eigenvectors:
                eigvals, self._eigenvectors[i] = np.linalg.eigh(dm)
                self._eigenvalues[i] = eigvals.real
            else:
                self._eigenvalues[i] = np.linalg.eigvalsh(dm).real

        self._frequencies = np.array(
            np.sqrt(abs(self._eigenvalues)) *
            np.sign(self._eigenvalues)) * self._factor

    def _set_group_velocities(self, group_velocity):
        group_velocity.set_q_points(self._qpoints)
        self._group_velocities = group_velocity.get_group_velocity()
Exemple #7
0
class Mesh:
    def __init__(self,
                 dynamical_matrix,
                 cell,
                 mesh,
                 shift=None,
                 is_time_reversal=False,
                 is_mesh_symmetry=True,
                 is_eigenvectors=False,
                 is_band_connection=False,
                 is_gamma_center=False,
                 group_velocity=None,
                 factor=VaspToTHz,
                 symprec=1e-5):
        self._mesh = np.array(mesh)
        self._is_band_connection=is_band_connection
        self._band_order = None
        self._is_eigenvectors = is_eigenvectors
        self._factor = factor
        self._cell = cell
        self._dynamical_matrix = dynamical_matrix
        # self._qpoints, self._weights = get_qpoints(self._mesh,
        #                                            self._cell,
        #                                            shift,
        #                                            is_gamma_center,
        #                                            is_time_reversal,
        #                                            symprec,
        #                                            is_symmetry)
        rotations  = Symmetry(self._cell).get_pointgroup_operations()
        self._gp = GridPoints(self._mesh,
                              np.linalg.inv(self._cell.get_cell()),
                              q_mesh_shift=shift,
                              is_gamma_center=is_gamma_center,
                              is_time_reversal=is_time_reversal,
                              rotations=rotations,
                              is_mesh_symmetry=is_mesh_symmetry)
        self._qpoints = self._gp.get_ir_qpoints()
        self._weights = self._gp.get_ir_grid_weights()

        self._eigenvalues = None
        self._eigenvectors = None
        self._set_eigenvalues()
        if self._is_band_connection:
            self._set_band_connection()

        self._group_velocities = None
        if group_velocity is not None:
            self._set_group_velocities(group_velocity)

    def get_dynamical_matrix(self):
        return self._dynamical_matrix

    def get_mesh_numbers(self):
        return self._mesh

    def get_qpoints(self):
        return self._qpoints

    def get_weights(self):
        return self._weights

    def get_grid_address(self):
        return self._gp.get_grid_address()

    def get_ir_grid_points(self):
        return self._gp.get_ir_grid_points()

    def get_grid_mapping_table(self):
        return self._gp.get_grid_mapping_table()

    def get_eigenvalues(self):
        return self._eigenvalues

    def get_frequencies(self):
        return self._frequencies

    def get_group_velocities(self):
        return self._group_velocities

    def get_eigenvectors(self):
        """
        Eigenvectors is a numpy array of three dimension.
        The first index runs through q-points.
        In the second and third indices, eigenvectors obtained
        using numpy.linalg.eigh are stored.
        
        The third index corresponds to the eigenvalue's index.
        The second index is for atoms [x1, y1, z1, x2, y2, z2, ...].
        """
        return self._eigenvectors

    def write_hdf5(self):
        import h5py
        f=h5py.File('mesh.hdf5', 'w')
        eigenvalues = self._eigenvalues
        natom = self._cell.get_number_of_atoms()
        f.create_dataset('mesh', data=self._mesh)
        f.create_dataset('nqpoint',data=self._qpoints.shape[0])
        f.create_dataset('q-position',data=self._qpoints)
        f.create_dataset('natom',data=natom)
        f.create_dataset('weight', data=self._weights)
        f.create_dataset('frequency',data=self._factor*
                                          np.sign(eigenvalues)*
                                          np.sqrt(np.abs(eigenvalues)))
        if self._group_velocities is not None:
            f.create_dataset('group_velocity', data=self._group_velocities)
        if self._is_eigenvectors:
            f.create_dataset('eigenvector_r',data=self._eigenvectors.real)
            f.create_dataset('eigenvector_i',data=self._eigenvectors.imag)
        if self._is_band_connection:
            f.create_dataset('band_order', data=self._band_order)

    def write_yaml(self):
        f = open('mesh.yaml', 'w')
        eigenvalues = self._eigenvalues
        natom = self._cell.get_number_of_atoms()
        f.write("mesh: [ %5d, %5d, %5d ]\n" % tuple(self._mesh))
        f.write("nqpoint: %-7d\n" % self._qpoints.shape[0])
        f.write("natom:   %-7d\n" % natom)
        f.write("phonon:\n")

        for i, q in enumerate(self._qpoints):
            f.write("- q-position: [ %12.7f, %12.7f, %12.7f ]\n" % tuple(q))
            f.write("  weight: %-5d\n" % self._weights[i])
            f.write("  band:\n")

            for j, eig in enumerate(eigenvalues[i]):
                f.write("  - # %d\n" % (j+1))
                if eig < 0:
                    freq = -np.sqrt(-eig)
                else:
                    freq = np.sqrt(eig)
                f.write("    frequency:  %15.10f\n" % (freq * self._factor))

                if self._group_velocities is not None:
                    f.write("    group_velocity: ")
                    f.write("[ %13.7f, %13.7f, %13.7f ]\n" %
                            tuple(self._group_velocities[i, j]))

                if self._band_order is not None:
                    f.write("    band_order: %-5d\n"%self._band_order[i, j])

                if self._is_eigenvectors:
                    f.write("    eigenvector:\n")
                    for k in range(natom):
                        f.write("    - # atom %d\n" % (k+1))
                        for l in (0,1,2):
                            f.write("      - [ %17.14f, %17.14f ]\n" %
                                    (self._eigenvectors[i,k*3+l,j].real,
                                     self._eigenvectors[i,k*3+l,j].imag))
            f.write("\n")

    def _set_eigenvalues(self):
        eigs = []
        vecs = []
        for q in self._qpoints:
            self._dynamical_matrix.set_dynamical_matrix(q)
            dm = self._dynamical_matrix.get_dynamical_matrix()

            if self._is_eigenvectors:
                val, vec = np.linalg.eigh(dm)
                eigs.append(val.real)
                vecs.append(vec)
            else:
                eigs.append(np.linalg.eigvalsh(dm).real)

        self._eigenvalues = np.array(eigs)
        if self._is_eigenvectors:
            self._eigenvectors = np.array(vecs)

        self._set_frequencies()

    def _set_band_connection(self):
        nband = self._cell.get_number_of_atoms() * 3
        nqpoint = len(self._qpoints)
        qpoints = np.dot(np.linalg.inv(self._cell.get_cell()), self._qpoints.T).T
        band_order = np.zeros((nqpoint, nband), dtype="intc")

        is_degenerate = np.zeros(len(self._eigenvalues), dtype="bool")

        degenerate = []
        for i, freq in  enumerate(self._frequencies):
            deg = get_degenerate_sets(freq, 1e-5)
            degenerate.append(deg)
            if len(deg) != nband:
                is_degenerate[i] = True

        nodegq = qpoints[np.where(is_degenerate == False)]
        indicesn = np.where(is_degenerate == False)[0]
        done = np.zeros(len(indicesn), dtype="bool")
        indicesd = np.where(is_degenerate)[0]
        qpts_dist = np.sum(nodegq ** 2, axis=-1)
        start_q = np.argmin(qpts_dist)
        i=start_q
        band_order[indicesn[start_q]] = np.arange(nband)
        while True:
            done[i]=True
            is_break = True
            for j in np.argsort(np.sum((nodegq-nodegq[i])**2, axis=-1)):
                if not done[j]:
                    is_break = False
                    break
            if is_break:
                break
            for i in np.argsort(np.sum((nodegq-nodegq[j])**2, axis=-1)):
                if done[i]:
                    break
            bi=indicesn[i]
            bj = indicesn[j]
            bo = self._estimate_band_connection(self._qpoints[bi], self._qpoints[bj], band_order[bi])
            band_order[bj] = bo
            i=j
        for id in indicesd:
            j = np.argmin(np.sum((nodegq-qpoints[id])**2, axis=-1))
            ij = indicesn[j]
            if (self._qpoints[id] == np.array([0.48, 0.48, 0])).all():
                self._estimate_band_connection(np.array([0.2, 0.2, 0]), np.array([0.48, 0.48, 0]), np.array([0,1,2,3,4,5]))
            bo = self._estimate_band_connection(self._qpoints[ij],
                                          self._qpoints[id],
                                          band_order[ij])
            band_order[id] = bo
        self._band_order = band_order


    def _estimate_band_connection(self, p, n, band_order_pre):
        self._dynamical_matrix.set_dynamical_matrix(p)
        e1, ev1 = np.linalg.eigh(self._dynamical_matrix.get_dynamical_matrix())
        fre1 = np.array(np.sqrt(abs(e1)) * np.sign(e1)) * self._factor
        self._dynamical_matrix.set_dynamical_matrix(n)
        e2, ev2 = np.linalg.eigh(self._dynamical_matrix.get_dynamical_matrix())
        fre2 = np.array(np.sqrt(abs(e2)) * np.sign(e2)) * self._factor
        deg1 = get_degenerate_sets(fre1, 1e-5)
        deg2 = get_degenerate_sets(fre2, 1e-5)
        assert len(deg1) >= len(deg2)
        mid_point = p + (n-p) * (0.5 +np.random.random() / 10)
        self._dynamical_matrix.set_dynamical_matrix(mid_point)
        evv, evm = np.linalg.eigh(self._dynamical_matrix.get_dynamical_matrix())
        frem = np.array(np.sqrt(abs(evv)) * np.sign(evv)) * self._factor
        degeneratem = get_degenerate_sets(frem, 1e-7)
        assert len(degeneratem) == len(deg1)
        b1 = estimate_band_connection(ev1, evm, band_order_pre, degeneratem, 0.9)
        if b1 is None:
            b1 = self._estimate_band_connection(p, mid_point, band_order_pre)
        b2 = estimate_band_connection(evm, ev2, b1, deg2, 0.9)
        if b2 is not None:
            return b2
        else:
            return self._estimate_band_connection(mid_point, n, b1)


    def _set_frequencies(self):
        ## This expression works only python >= 2.5
        #  frequencies = []
        # for eigs in self._eigenvalues:
        #     frequencies.append(
        #         [np.sqrt(x) if x > 0 else -np.sqrt(-x) for x in eigs])
        
        self._frequencies = np.array(np.sqrt(abs(self._eigenvalues)) *
                                     np.sign(self._eigenvalues)) * self._factor

    def _set_group_velocities(self, group_velocity):
        group_velocity.set_q_points(self._qpoints)
        self._group_velocities = group_velocity.get_group_velocity()
Exemple #8
0
class Mesh:
    def __init__(
        self,
        dynamical_matrix,
        mesh,
        shift=None,
        is_time_reversal=True,
        is_mesh_symmetry=True,
        is_eigenvectors=False,
        is_gamma_center=False,
        group_velocity=None,
        rotations=None,  # Point group operations in real space
        factor=VaspToTHz,
        use_lapack_solver=False,
    ):

        self._mesh = np.array(mesh, dtype="intc")
        self._is_eigenvectors = is_eigenvectors
        self._factor = factor
        self._cell = dynamical_matrix.get_primitive()
        self._dynamical_matrix = dynamical_matrix
        self._use_lapack_solver = use_lapack_solver

        self._gp = GridPoints(
            self._mesh,
            np.linalg.inv(self._cell.get_cell()),
            q_mesh_shift=shift,
            is_gamma_center=is_gamma_center,
            is_time_reversal=is_time_reversal,
            rotations=rotations,
            is_mesh_symmetry=is_mesh_symmetry,
        )

        self._qpoints = self._gp.get_ir_qpoints()
        self._weights = self._gp.get_ir_grid_weights()

        self._frequencies = None
        self._eigenvalues = None
        self._eigenvectors = None
        self._set_phonon()

        self._group_velocities = None
        if group_velocity is not None:
            self._set_group_velocities(group_velocity)

    def get_dynamical_matrix(self):
        return self._dynamical_matrix

    def get_mesh_numbers(self):
        return self._mesh

    def get_qpoints(self):
        return self._qpoints

    def get_weights(self):
        return self._weights

    def get_grid_address(self):
        return self._gp.get_grid_address()

    def get_ir_grid_points(self):
        return self._gp.get_ir_grid_points()

    def get_grid_mapping_table(self):
        return self._gp.get_grid_mapping_table()

    def get_eigenvalues(self):
        return self._eigenvalues

    def get_frequencies(self):
        return self._frequencies

    def get_group_velocities(self):
        return self._group_velocities

    def get_eigenvectors(self):
        """
        Eigenvectors is a numpy array of three dimension.
        The first index runs through q-points.
        In the second and third indices, eigenvectors obtained
        using numpy.linalg.eigh are stored.
        
        The third index corresponds to the eigenvalue's index.
        The second index is for atoms [x1, y1, z1, x2, y2, z2, ...].
        """
        return self._eigenvectors

    def write_hdf5(self):
        import h5py

        with h5py.File("mesh.hdf5", "w") as w:
            w.create_dataset("mesh", data=self._mesh)
            w.create_dataset("qpoint", data=self._qpoints)
            w.create_dataset("weight", data=self._weights)
            w.create_dataset("frequency", data=self._frequencies)
            if self._eigenvectors is not None:
                w.create_dataset("eigenvector", data=self._eigenvectors)
            if self._group_velocities is not None:
                w.create_dataset("group_velocity", data=self._group_velocities)

    def write_yaml(self):
        w = open("mesh.yaml", "w")
        eigenvalues = self._eigenvalues
        natom = self._cell.get_number_of_atoms()
        rec_lattice = np.linalg.inv(self._cell.get_cell())  # column vectors
        supercell = self._dynamical_matrix.get_supercell()
        smat = supercell.get_supercell_matrix()
        pmat = self._cell.get_primitive_matrix()
        tmat = np.rint(np.dot(np.linalg.inv(pmat), smat)).astype(int)

        w.write("mesh: [ %5d, %5d, %5d ]\n" % tuple(self._mesh))
        w.write("nqpoint: %-7d\n" % self._qpoints.shape[0])
        w.write("reciprocal_lattice:\n")
        for vec, axis in zip(rec_lattice.T, ("a*", "b*", "c*")):
            w.write("- [ %12.8f, %12.8f, %12.8f ] # %2s\n" % (tuple(vec) + (axis,)))
        w.write("natom:   %-7d\n" % natom)
        w.write(str(PhonopyAtoms(atoms=self._cell)))
        w.write("\n")
        w.write("supercell_matrix:\n")
        for v in tmat:
            w.write("- [ %4d, %4d, %4d ]\n" % tuple(v))

        w.write("\n")
        w.write("phonon:\n")

        for i, q in enumerate(self._qpoints):
            w.write("- q-position: [ %12.7f, %12.7f, %12.7f ]\n" % tuple(q))
            w.write("  weight: %-5d\n" % self._weights[i])
            w.write("  band:\n")

            for j, freq in enumerate(self._frequencies[i]):
                w.write("  - # %d\n" % (j + 1))
                w.write("    frequency:  %15.10f\n" % freq)

                if self._group_velocities is not None:
                    w.write("    group_velocity: ")
                    w.write("[ %13.7f, %13.7f, %13.7f ]\n" % tuple(self._group_velocities[i, j]))

                if self._is_eigenvectors:
                    w.write("    eigenvector:\n")
                    for k in range(natom):
                        w.write("    - # atom %d\n" % (k + 1))
                        for l in (0, 1, 2):
                            w.write(
                                "      - [ %17.14f, %17.14f ]\n"
                                % (self._eigenvectors[i, k * 3 + l, j].real, self._eigenvectors[i, k * 3 + l, j].imag)
                            )
            w.write("\n")

    def _set_phonon(self):
        num_band = self._cell.get_number_of_atoms() * 3
        num_qpoints = len(self._qpoints)

        self._eigenvalues = np.zeros((num_qpoints, num_band), dtype="double")
        self._frequencies = np.zeros_like(self._eigenvalues)
        if self._is_eigenvectors or self._use_lapack_solver:
            self._eigenvectors = np.zeros((num_qpoints, num_band, num_band), dtype="complex128")

        if self._use_lapack_solver:
            from phonopy.phonon.solver import get_phonons_at_qpoints

            get_phonons_at_qpoints(
                self._frequencies,
                self._eigenvectors,
                self._dynamical_matrix,
                self._qpoints,
                self._factor,
                nac_q_direction=None,
                lapack_zheev_uplo="L",
            )
            self._eigenvalues = (
                np.array(self._frequencies ** 2 * np.sign(self._frequencies), dtype="double", order="C")
                / self._factor ** 2
            )
            if not self._is_eigenvectors:
                self._eigenvalues = None
        else:
            for i, q in enumerate(self._qpoints):
                self._dynamical_matrix.set_dynamical_matrix(q)
                dm = self._dynamical_matrix.get_dynamical_matrix()
                if self._is_eigenvectors:
                    eigvals, self._eigenvectors[i] = np.linalg.eigh(dm)
                    self._eigenvalues[i] = eigvals.real
                else:
                    self._eigenvalues[i] = np.linalg.eigvalsh(dm).real
            self._frequencies = (
                np.array(np.sqrt(abs(self._eigenvalues)) * np.sign(self._eigenvalues), dtype="double", order="C")
                * self._factor
            )

    def _set_group_velocities(self, group_velocity):
        group_velocity.set_q_points(self._qpoints)
        self._group_velocities = group_velocity.get_group_velocity()