Beispiel #1
0
class Phono4py:
    def __init__(
        self,
        unitcell,
        supercell_matrix,
        primitive_matrix=None,
        mesh=None,
        band_indices=None,
        frequency_factor_to_THz=VaspToTHz,
        is_symmetry=True,
        is_nosym=False,
        symprec=1e-3,
        cutoff_frequency=1e-4,
        log_level=False,
        lapack_zheev_uplo="L",
    ):
        self._unitcell = unitcell
        self._supercell_matrix = supercell_matrix
        self._primitive_matrix = primitive_matrix
        if mesh is None:
            self._mesh = None
        else:
            self._mesh = np.array(mesh, dtype="intc")
        self._frequency_factor_to_THz = frequency_factor_to_THz
        self._is_symmetry = is_symmetry
        self._is_nosym = is_nosym
        self._symprec = symprec
        self._cutoff_frequency = cutoff_frequency
        self._log_level = log_level
        self._lapack_zheev_uplo = lapack_zheev_uplo

        self._supercell = None
        self._primitive = None
        self._build_supercell()
        self._build_primitive_cell()
        self._supercells_with_displacements = None
        self._displacement_dataset = None

        if band_indices is None:
            num_band = self._primitive.get_number_of_atoms() * 3
            self._band_indices = [np.arange(num_band, dtype="intc")]
        else:
            self._band_indices = band_indices
        self._band_indices_flatten = np.array([x for bi in self._band_indices for x in bi], dtype="intc")
        self._symmetry = Symmetry(self._supercell, self._symprec, self._is_symmetry)
        self._frequency_shifts = None

    def get_fc2(self):
        return self._fc2

    def set_fc2(self, fc2):
        self._fc2 = fc2

    def get_fc3(self):
        return self._fc3

    def set_fc3(self, fc3):
        self._fc3 = fc3

    def get_fc4(self):
        return self._fc4

    def set_fc4(self, fc4):
        self._fc4 = fc4

    def get_primitive(self):
        return self._primitive

    def get_unitcell(self):
        return self._unitcell

    def get_supercell(self):
        return self._supercell

    def get_symmetry(self):
        return self._symmetry

    def get_displacement_dataset(self):
        return self._displacement_dataset

    def get_supercells_with_displacements(self):
        if self._supercells_with_displacements is None:
            self._build_supercells_with_displacements()
        return self._supercells_with_displacements

    def generate_displacements(self, distance=0.03, is_plusminus="auto", is_diagonal=True):
        direction_dataset = get_fourth_order_displacements(
            self._supercell, self._symmetry, is_plusminus=is_plusminus, is_diagonal=is_diagonal
        )
        self._displacement_dataset = direction_to_displacement(direction_dataset, distance, self._supercell)

    def produce_fc4(
        self,
        forces_fc4,
        displacement_dataset,
        translational_symmetry_type=0,
        is_permutation_symmetry=False,
        is_permutation_symmetry_fc3=False,
        is_permutation_symmetry_fc2=False,
    ):
        disp_dataset = displacement_dataset
        file_count = 0
        for disp1 in disp_dataset["first_atoms"]:
            disp1["forces"] = forces_fc4[file_count]
            file_count += 1
        self._fc2 = get_fc2(self._supercell, self._symmetry, disp_dataset)
        if is_permutation_symmetry_fc2:
            set_permutation_symmetry(self._fc2)
        if translational_symmetry_type:
            set_translational_invariance(self._fc2, translational_symmetry_type=translational_symmetry_type)

        for disp1 in disp_dataset["first_atoms"]:
            for disp2 in disp1["second_atoms"]:
                disp2["forces"] = forces_fc4[file_count]
                disp2["delta_forces"] = disp2["forces"] - disp1["forces"]
                file_count += 1

        self._fc3 = get_fc3(
            self._supercell,
            disp_dataset,
            self._fc2,
            self._symmetry,
            translational_symmetry_type=translational_symmetry_type,
            is_permutation_symmetry=is_permutation_symmetry_fc3,
            verbose=self._log_level,
        )

        for disp1 in disp_dataset["first_atoms"]:
            for disp2 in disp1["second_atoms"]:
                for disp3 in disp2["third_atoms"]:
                    disp3["delta_forces"] = forces_fc4[file_count] - disp2["forces"]
                    file_count += 1

        self._fc4 = get_fc4(
            self._supercell,
            disp_dataset,
            self._fc3,
            self._symmetry,
            translational_symmetry_type=translational_symmetry_type,
            is_permutation_symmetry=is_permutation_symmetry,
            verbose=self._log_level,
        )

    def set_frequency_shift(self, temperatures=None):
        self._interaction = FrequencyShift(
            self._fc4,
            self._supercell,
            self._primitive,
            self._mesh,
            temperatures=temperatures,
            band_indices=self._band_indices_flatten,
            frequency_factor_to_THz=self._frequency_factor_to_THz,
            is_nosym=self._is_nosym,
            symprec=self._symprec,
            cutoff_frequency=self._cutoff_frequency,
            log_level=self._log_level,
            lapack_zheev_uplo=self._lapack_zheev_uplo,
        )
        self._grid_address = self._interaction.get_grid_address()
        self._frequencies = self._interaction.get_phonons()[0]
        self._temperatures = temperatures

    def set_dynamical_matrix(
        self, fc2, supercell, primitive, nac_params=None, nac_q_direction=None, frequency_scale_factor=None
    ):
        self._interaction.set_dynamical_matrix(
            fc2, supercell, primitive, nac_params=nac_params, frequency_scale_factor=frequency_scale_factor
        )
        self._interaction.set_nac_q_direction(nac_q_direction=nac_q_direction)

    def run_frequency_shift(self, grid_points):
        if self._log_level:
            print "------------------------",
            print "Frequency shifts of fc4 ",
            print "------------------------"

        freq_shifts = []
        num_band = len(self._band_indices_flatten)
        for i, gp in enumerate(grid_points):
            qpoint = self._grid_address[gp].astype(float) / self._mesh
            if self._log_level:
                print "=========================",
                print "Grid point %d (%d/%d)" % (gp, i + 1, len(grid_points)),
                print "========================="
                print "q-point:", qpoint
            self._interaction.set_grid_point(gp)
            self._interaction.run()
            f_shifts_at_temps = self._interaction.get_frequency_shifts()
            if self._log_level:
                print "Harmonic phonon frequencies:"
                freqs = self._frequencies[gp][self._band_indices_flatten]
                print "%7s " % "",
                print ("%8.4f " * num_band) % tuple(freqs)
                print "Frequency shifts:"
                for t, f_shift in zip(self._temperatures, f_shifts_at_temps):
                    print "%7.1f " % t,
                    print ("%8.4f " * num_band) % tuple(f_shift)
            freq_shifts.append(f_shifts_at_temps)

        self._frequency_shifts = np.array(freq_shifts, dtype="double")

        for i, gp in enumerate(grid_points):
            for j, bi in enumerate(self._band_indices):
                pos = 0
                for k in range(j):
                    pos += len(self._band_indices[k])

                write_frequency_shift(gp, bi, self._temperatures, freq_shifts[i][:, pos : (pos + len(bi))], self._mesh)

    def get_frequency_shift(self):
        return self._frequency_shifts

    def _build_supercells_with_displacements(self):
        supercells = []
        magmoms = self._supercell.get_magnetic_moments()
        masses = self._supercell.get_masses()
        numbers = self._supercell.get_atomic_numbers()
        lattice = self._supercell.get_cell()

        for disp1 in self._displacement_dataset["first_atoms"]:
            disp_cart1 = disp1["displacement"]
            positions = self._supercell.get_positions()
            positions[disp1["number"]] += disp_cart1
            supercells.append(
                Atoms(numbers=numbers, masses=masses, magmoms=magmoms, positions=positions, cell=lattice, pbc=True)
            )

        for disp1 in self._displacement_dataset["first_atoms"]:
            for disp2 in disp1["second_atoms"]:
                positions = self._supercell.get_positions()
                positions[disp1["number"]] += disp_cart1
                positions[disp2["number"]] += disp2["displacement"]
                supercells.append(
                    Atoms(numbers=numbers, masses=masses, magmoms=magmoms, positions=positions, cell=lattice, pbc=True)
                )

        for disp1 in self._displacement_dataset["first_atoms"]:
            for disp2 in disp1["second_atoms"]:
                for disp3 in disp2["third_atoms"]:
                    positions = self._supercell.get_positions()
                    positions[disp1["number"]] += disp_cart1
                    positions[disp2["number"]] += disp2["displacement"]
                    positions[disp3["number"]] += disp3["displacement"]
                    supercells.append(
                        Atoms(
                            numbers=numbers, masses=masses, magmoms=magmoms, positions=positions, cell=lattice, pbc=True
                        )
                    )

        self._supercells_with_displacements = supercells

    def _build_supercell(self):
        self._supercell = get_supercell(self._unitcell, self._supercell_matrix, self._symprec)

    def _build_primitive_cell(self):
        """
        primitive_matrix:
          Relative axes of primitive cell to the input unit cell.
          Relative axes to the supercell is calculated by:
             supercell_matrix^-1 * primitive_matrix
          Therefore primitive cell lattice is finally calculated by:
             (supercell_lattice * (supercell_matrix)^-1 * primitive_matrix)^T
        """
        self._primitive = self._get_primitive_cell(self._supercell, self._supercell_matrix, self._primitive_matrix)

    def _get_primitive_cell(self, supercell, supercell_matrix, primitive_matrix):
        inv_supercell_matrix = np.linalg.inv(supercell_matrix)
        if primitive_matrix is None:
            t_mat = inv_supercell_matrix
        else:
            t_mat = np.dot(inv_supercell_matrix, primitive_matrix)

        return get_primitive(supercell, t_mat, self._symprec)
Beispiel #2
0
class Phono4py:
    def __init__(self,
                 unitcell,
                 supercell_matrix,
                 primitive_matrix=None,
                 mesh=None,
                 band_indices=None,
                 frequency_factor_to_THz=VaspToTHz,
                 is_symmetry=True,
                 is_nosym=False,
                 symprec=1e-3,
                 cutoff_frequency=1e-4,
                 log_level=False,
                 lapack_zheev_uplo='L'):
        self._unitcell = unitcell
        self._supercell_matrix = supercell_matrix
        self._primitive_matrix = primitive_matrix
        if mesh is None:
            self._mesh = None
        else:
            self._mesh = np.array(mesh, dtype='intc')
        self._frequency_factor_to_THz = frequency_factor_to_THz
        self._is_symmetry = is_symmetry
        self._is_nosym = is_nosym
        self._symprec = symprec
        self._cutoff_frequency = cutoff_frequency
        self._log_level = log_level
        self._lapack_zheev_uplo = lapack_zheev_uplo

        self._supercell = None
        self._primitive = None
        self._build_supercell()
        self._build_primitive_cell()
        self._supercells_with_displacements = None
        self._displacement_dataset = None

        if band_indices is None:
            num_band = self._primitive.get_number_of_atoms() * 3
            self._band_indices = [np.arange(num_band, dtype='intc')]
        else:
            self._band_indices = band_indices
        self._band_indices_flatten = np.array(
            [x for bi in self._band_indices for x in bi], dtype='intc')
        self._symmetry = Symmetry(self._supercell, self._symprec,
                                  self._is_symmetry)
        self._frequency_shifts = None

    def get_fc2(self):
        return self._fc2

    def set_fc2(self, fc2):
        self._fc2 = fc2

    def get_fc3(self):
        return self._fc3

    def set_fc3(self, fc3):
        self._fc3 = fc3

    def get_fc4(self):
        return self._fc4

    def set_fc4(self, fc4):
        self._fc4 = fc4

    def get_primitive(self):
        return self._primitive

    def get_unitcell(self):
        return self._unitcell

    def get_supercell(self):
        return self._supercell

    def get_symmetry(self):
        return self._symmetry

    def get_displacement_dataset(self):
        return self._displacement_dataset

    def get_supercells_with_displacements(self):
        if self._supercells_with_displacements is None:
            self._build_supercells_with_displacements()
        return self._supercells_with_displacements

    def generate_displacements(self,
                               distance=0.03,
                               is_plusminus='auto',
                               is_diagonal=True):
        direction_dataset = get_fourth_order_displacements(
            self._supercell,
            self._symmetry,
            is_plusminus=is_plusminus,
            is_diagonal=is_diagonal)
        self._displacement_dataset = direction_to_displacement(
            direction_dataset, distance, self._supercell)

    def produce_fc4(self,
                    forces_fc4,
                    displacement_dataset,
                    translational_symmetry_type=0,
                    is_permutation_symmetry=False,
                    is_permutation_symmetry_fc3=False,
                    is_permutation_symmetry_fc2=False):
        disp_dataset = displacement_dataset
        file_count = 0
        for disp1 in disp_dataset['first_atoms']:
            disp1['forces'] = forces_fc4[file_count]
            file_count += 1
        self._fc2 = get_fc2(self._supercell, self._symmetry, disp_dataset)
        if is_permutation_symmetry_fc2:
            set_permutation_symmetry(self._fc2)
        if translational_symmetry_type:
            set_translational_invariance(
                self._fc2,
                translational_symmetry_type=translational_symmetry_type)

        for disp1 in disp_dataset['first_atoms']:
            for disp2 in disp1['second_atoms']:
                disp2['forces'] = forces_fc4[file_count]
                disp2['delta_forces'] = disp2['forces'] - disp1['forces']
                file_count += 1

        self._fc3 = get_fc3(
            self._supercell,
            disp_dataset,
            self._fc2,
            self._symmetry,
            translational_symmetry_type=translational_symmetry_type,
            is_permutation_symmetry=is_permutation_symmetry_fc3,
            verbose=self._log_level)

        for disp1 in disp_dataset['first_atoms']:
            for disp2 in disp1['second_atoms']:
                for disp3 in disp2['third_atoms']:
                    disp3['delta_forces'] = (forces_fc4[file_count] -
                                             disp2['forces'])
                    file_count += 1

        self._fc4 = get_fc4(
            self._supercell,
            disp_dataset,
            self._fc3,
            self._symmetry,
            translational_symmetry_type=translational_symmetry_type,
            is_permutation_symmetry=is_permutation_symmetry,
            verbose=self._log_level)

    def set_frequency_shift(self, temperatures=None):
        self._interaction = FrequencyShift(
            self._fc4,
            self._supercell,
            self._primitive,
            self._mesh,
            temperatures=temperatures,
            band_indices=self._band_indices_flatten,
            frequency_factor_to_THz=self._frequency_factor_to_THz,
            is_nosym=self._is_nosym,
            symprec=self._symprec,
            cutoff_frequency=self._cutoff_frequency,
            log_level=self._log_level,
            lapack_zheev_uplo=self._lapack_zheev_uplo)
        self._grid_address = self._interaction.get_grid_address()
        self._frequencies = self._interaction.get_phonons()[0]
        self._temperatures = temperatures

    def set_dynamical_matrix(self,
                             fc2,
                             supercell,
                             primitive,
                             nac_params=None,
                             nac_q_direction=None,
                             frequency_scale_factor=None):
        self._interaction.set_dynamical_matrix(
            fc2,
            supercell,
            primitive,
            nac_params=nac_params,
            frequency_scale_factor=frequency_scale_factor)
        self._interaction.set_nac_q_direction(nac_q_direction=nac_q_direction)

    def run_frequency_shift(self, grid_points):
        if self._log_level:
            print "------------------------",
            print "Frequency shifts of fc4 ",
            print "------------------------"

        freq_shifts = []
        num_band = len(self._band_indices_flatten)
        for i, gp in enumerate(grid_points):
            qpoint = self._grid_address[gp].astype(float) / self._mesh
            if self._log_level:
                print "=========================",
                print "Grid point %d (%d/%d)" % (gp, i + 1, len(grid_points)),
                print "========================="
                print "q-point:", qpoint
            self._interaction.set_grid_point(gp)
            self._interaction.run()
            f_shifts_at_temps = self._interaction.get_frequency_shifts()
            if self._log_level:
                print "Harmonic phonon frequencies:"
                freqs = self._frequencies[gp][self._band_indices_flatten]
                print "%7s " % "",
                print("%8.4f " * num_band) % tuple(freqs)
                print "Frequency shifts:"
                for t, f_shift in zip(self._temperatures, f_shifts_at_temps):
                    print "%7.1f " % t,
                    print("%8.4f " * num_band) % tuple(f_shift)
            freq_shifts.append(f_shifts_at_temps)

        self._frequency_shifts = np.array(freq_shifts, dtype='double')

        for i, gp in enumerate(grid_points):
            for j, bi in enumerate(self._band_indices):
                pos = 0
                for k in range(j):
                    pos += len(self._band_indices[k])

                write_frequency_shift(gp, bi, self._temperatures,
                                      freq_shifts[i][:, pos:(pos + len(bi))],
                                      self._mesh)

    def get_frequency_shift(self):
        return self._frequency_shifts

    def _build_supercells_with_displacements(self):
        supercells = []
        magmoms = self._supercell.get_magnetic_moments()
        masses = self._supercell.get_masses()
        numbers = self._supercell.get_atomic_numbers()
        lattice = self._supercell.get_cell()

        for disp1 in self._displacement_dataset['first_atoms']:
            disp_cart1 = disp1['displacement']
            positions = self._supercell.get_positions()
            positions[disp1['number']] += disp_cart1
            supercells.append(
                Atoms(numbers=numbers,
                      masses=masses,
                      magmoms=magmoms,
                      positions=positions,
                      cell=lattice,
                      pbc=True))

        for disp1 in self._displacement_dataset['first_atoms']:
            for disp2 in disp1['second_atoms']:
                positions = self._supercell.get_positions()
                positions[disp1['number']] += disp_cart1
                positions[disp2['number']] += disp2['displacement']
                supercells.append(
                    Atoms(numbers=numbers,
                          masses=masses,
                          magmoms=magmoms,
                          positions=positions,
                          cell=lattice,
                          pbc=True))

        for disp1 in self._displacement_dataset['first_atoms']:
            for disp2 in disp1['second_atoms']:
                for disp3 in disp2['third_atoms']:
                    positions = self._supercell.get_positions()
                    positions[disp1['number']] += disp_cart1
                    positions[disp2['number']] += disp2['displacement']
                    positions[disp3['number']] += disp3['displacement']
                    supercells.append(
                        Atoms(numbers=numbers,
                              masses=masses,
                              magmoms=magmoms,
                              positions=positions,
                              cell=lattice,
                              pbc=True))

        self._supercells_with_displacements = supercells

    def _build_supercell(self):
        self._supercell = get_supercell(self._unitcell, self._supercell_matrix,
                                        self._symprec)

    def _build_primitive_cell(self):
        """
        primitive_matrix:
          Relative axes of primitive cell to the input unit cell.
          Relative axes to the supercell is calculated by:
             supercell_matrix^-1 * primitive_matrix
          Therefore primitive cell lattice is finally calculated by:
             (supercell_lattice * (supercell_matrix)^-1 * primitive_matrix)^T
        """
        self._primitive = self._get_primitive_cell(self._supercell,
                                                   self._supercell_matrix,
                                                   self._primitive_matrix)

    def _get_primitive_cell(self, supercell, supercell_matrix,
                            primitive_matrix):
        inv_supercell_matrix = np.linalg.inv(supercell_matrix)
        if primitive_matrix is None:
            t_mat = inv_supercell_matrix
        else:
            t_mat = np.dot(inv_supercell_matrix, primitive_matrix)

        return get_primitive(supercell, t_mat, self._symprec)
Beispiel #3
0
class Phono4py:
    def __init__(self,
                 fc4,
                 supercell,
                 primitive,
                 mesh,
                 band_indices=None,
                 frequency_factor_to_THz=VaspToTHz,
                 is_nosym=False,
                 symprec=1e-3,
                 cutoff_frequency=1e-4,
                 log_level=False,
                 lapack_zheev_uplo='L'):
        self._fc4 = fc4
        self._supercell = supercell
        self._primitive = primitive
        self._mesh = np.intc(mesh)
        if band_indices is None:
            self._band_indices = [
                np.arange(primitive.get_number_of_atoms() * 3)
            ]
        else:
            self._band_indices = band_indices
        self._frequency_factor_to_THz = frequency_factor_to_THz
        self._is_nosym = is_nosym
        self._symprec = symprec
        self._cutoff_frequency = cutoff_frequency
        self._log_level = log_level
        self._lapack_zheev_uplo = lapack_zheev_uplo

        self._band_indices_flatten = np.intc(
            [x for bi in self._band_indices for x in bi])

        self._frequency_shifts = None

    def set_frequency_shift(self, temperatures=None):
        self._interaction = FrequencyShift(
            self._fc4,
            self._supercell,
            self._primitive,
            self._mesh,
            temperatures=temperatures,
            band_indices=self._band_indices_flatten,
            frequency_factor_to_THz=self._frequency_factor_to_THz,
            is_nosym=self._is_nosym,
            symprec=self._symprec,
            cutoff_frequency=self._cutoff_frequency,
            log_level=self._log_level,
            lapack_zheev_uplo=self._lapack_zheev_uplo)

    def set_dynamical_matrix(self,
                             fc2,
                             supercell,
                             primitive,
                             nac_params=None,
                             nac_q_direction=None,
                             frequency_scale_factor=None):
        self._interaction.set_dynamical_matrix(
            fc2,
            supercell,
            primitive,
            nac_params=nac_params,
            frequency_scale_factor=frequency_scale_factor)
        self._interaction.set_nac_q_direction(nac_q_direction=nac_q_direction)

    def run_frequency_shift(self, grid_points):
        if self._log_level:
            print "----- Frequency shifts of fc4 -----"

        freq_shifts = []
        for i, gp in enumerate(grid_points):
            if self._log_level:
                print "=====================",
                print "Grid point %d (%d/%d)" % (gp, i + 1, len(grid_points)),
                print "====================="
            self._interaction.set_grid_point(gp)
            self._interaction.run()
            freq_shifts.append(self._interaction.get_frequency_shifts())

        self._frequency_shifts = np.double(freq_shifts)
        print self._frequency_shifts

    def get_frequency_shift(self):
        return self._frequency_shifts
Beispiel #4
0
class Phono4py:
    def __init__(self,
                 fc4,
                 supercell,
                 primitive,
                 mesh,
                 band_indices=None,
                 frequency_factor_to_THz=VaspToTHz,
                 is_nosym=False,
                 symprec=1e-3,
                 cutoff_frequency=1e-4,
                 log_level=False,
                 lapack_zheev_uplo='L'):
        self._fc4 = fc4
        self._supercell = supercell
        self._primitive = primitive
        self._mesh = np.intc(mesh)
        if band_indices is None:
            self._band_indices = [
                np.arange(primitive.get_number_of_atoms() * 3)]
        else:
            self._band_indices = band_indices
        self._frequency_factor_to_THz = frequency_factor_to_THz
        self._is_nosym = is_nosym
        self._symprec = symprec
        self._cutoff_frequency = cutoff_frequency
        self._log_level = log_level
        self._lapack_zheev_uplo = lapack_zheev_uplo

        self._band_indices_flatten = np.intc(
            [x for bi in self._band_indices for x in bi])

        self._frequency_shifts = None
        
    def set_frequency_shift(self, temperatures=None):
        self._interaction = FrequencyShift(
            self._fc4,
            self._supercell,
            self._primitive,
            self._mesh,
            temperatures=temperatures,
            band_indices=self._band_indices_flatten,
            frequency_factor_to_THz=self._frequency_factor_to_THz,
            is_nosym=self._is_nosym,
            symprec=self._symprec,
            cutoff_frequency=self._cutoff_frequency,
            log_level=self._log_level,
            lapack_zheev_uplo=self._lapack_zheev_uplo)

    def set_dynamical_matrix(self,
                             fc2,
                             supercell,
                             primitive,
                             nac_params=None,
                             nac_q_direction=None,
                             frequency_scale_factor=None):
        self._interaction.set_dynamical_matrix(
            fc2,
            supercell,
            primitive,
            nac_params=nac_params,
            frequency_scale_factor=frequency_scale_factor)
        self._interaction.set_nac_q_direction(nac_q_direction=nac_q_direction)

    def run_frequency_shift(self, grid_points):
        if self._log_level:
            print "----- Frequency shifts of fc4 -----"
        
        freq_shifts = []
        for i, gp in enumerate(grid_points):
            if self._log_level:
                print "=====================",
                print "Grid point %d (%d/%d)" % (gp, i + 1, len(grid_points)),
                print "====================="
            self._interaction.set_grid_point(gp)
            self._interaction.run()
            freq_shifts.append(self._interaction.get_frequency_shifts())

        self._frequency_shifts = np.double(freq_shifts)
        print self._frequency_shifts

    def get_frequency_shift(self):
        return self._frequency_shifts