def _set_triplets_integration_weights_c(g, interaction, frequency_points): import anharmonic._phono3py as phono3c reciprocal_lattice = np.linalg.inv(interaction.get_primitive().get_cell()) mesh = interaction.get_mesh_numbers() thm = TetrahedronMethod(reciprocal_lattice, mesh=mesh) grid_address = interaction.get_grid_address() bz_map = interaction.get_bz_map() triplets_at_q = interaction.get_triplets_at_q()[0] unique_vertices = thm.get_unique_tetrahedra_vertices() for i, j in zip((1, 2), (1, -1)): neighboring_grid_points = np.zeros( len(unique_vertices) * len(triplets_at_q), dtype='intc') phono3c.neighboring_grid_points( neighboring_grid_points, triplets_at_q[:, i].flatten(), j * unique_vertices, mesh, grid_address, bz_map) interaction.set_phonon(np.unique(neighboring_grid_points)) phono3c.triplets_integration_weights( g, np.array(frequency_points, dtype='double'), thm.get_tetrahedra(), mesh, triplets_at_q, interaction.get_phonons()[0], grid_address, bz_map)
def _set_triplets_integration_weights_c(g, interaction, frequency_points, neighboring_phonons=True): import anharmonic._phono3py as phono3c reciprocal_lattice = np.linalg.inv(interaction.get_primitive().get_cell()) mesh = interaction.get_mesh_numbers() thm = TetrahedronMethod(reciprocal_lattice, mesh=mesh) grid_address = interaction.get_grid_address() bz_map = interaction.get_bz_map() triplets_at_q = interaction.get_triplets_at_q()[0] if neighboring_phonons: unique_vertices = thm.get_unique_tetrahedra_vertices() for i, j in zip((1, 2), (1, -1)): neighboring_grid_points = np.zeros(len(unique_vertices) * len(triplets_at_q), dtype='intc') phono3c.neighboring_grid_points(neighboring_grid_points, triplets_at_q[:, i].flatten(), j * unique_vertices, mesh, grid_address, bz_map) interaction.set_phonon(np.unique(neighboring_grid_points)) phono3c.triplets_integration_weights(g, frequency_points, thm.get_tetrahedra(), mesh, triplets_at_q, interaction.get_phonons()[0], grid_address, bz_map)
def _set_triplets_integration_weights_c(g, interaction, frequency_points=None, neighboring_phonons=True, triplets_at_q=None, band_indices=None, is_triplet_symmetry=False): import anharmonic._phono3py as phono3c if triplets_at_q == None: triplets_at_q = interaction.get_triplets_at_q()[0] if len(triplets_at_q) == 0: return reciprocal_lattice = np.linalg.inv(interaction.get_primitive().get_cell()) mesh = interaction.get_mesh_numbers() thm = TetrahedronMethod(reciprocal_lattice, mesh=mesh) grid_address = interaction.get_grid_address() bz_map = interaction.get_bz_map() if neighboring_phonons: unique_vertices = thm.get_unique_tetrahedra_vertices() for i in (1, 2, 0): # index inside a triplet for j in (1, -1): neighboring_grid_points = np.zeros( len(unique_vertices) * len(np.unique(triplets_at_q[:, i])), dtype='intc') phono3c.neighboring_grid_points( neighboring_grid_points, np.unique(triplets_at_q[:, i]).astype("intc"), j * unique_vertices, mesh, grid_address, bz_map) interaction.set_phonons(np.unique(neighboring_grid_points)) frequencies = interaction.get_phonons()[0] if len(np.where(mesh == 1)[0]) < 2: if band_indices is None: phono3c.triplets_integration_weights_fpoints( g, frequency_points, thm.get_tetrahedra().astype("intc").copy(), mesh, triplets_at_q, frequencies, grid_address, bz_map) else: phono3c.triplets_integration_weights( g, thm.get_tetrahedra().astype("intc").copy(), mesh, triplets_at_q, frequencies, np.array(band_indices, dtype='intc'), grid_address, bz_map, is_triplet_symmetry) else: # 1D case possible_shift = np.array((np.array(mesh) != 1), dtype='intc') relative_address = np.array( [[[0, 0, 0], possible_shift], [[0, 0, 0], -possible_shift]], dtype="intc") if band_indices is None: phono3c.triplets_integration_weights_1D_fpoints( g, frequency_points, relative_address, mesh, triplets_at_q, frequencies, grid_address, bz_map) else: phono3c.triplets_integration_weights_1D( g, relative_address, mesh, triplets_at_q, frequencies, np.array(band_indices, dtype='intc'), grid_address, bz_map, is_triplet_symmetry)
def run_at_frequencies(self, value='I', division_number=201, frequency_points=None): if frequency_points is None: max_frequency = np.amax(self._frequencies) min_frequency = np.amin(self._frequencies) self._frequency_points = np.linspace(min_frequency, max_frequency, division_number) else: self._frequency_points = frequency_points num_ir_grid_points = len(self._ir_grid_points) num_band = self._cell.get_number_of_atoms() * 3 num_freqs = len(self._frequency_points) self._integration_weights = np.zeros( (num_freqs, num_band, num_ir_grid_points), dtype='double') reciprocal_lattice = np.linalg.inv(self._cell.get_cell()) self._tm = TetrahedronMethod(reciprocal_lattice, mesh=self._mesh) self._relative_grid_address = self._tm.get_tetrahedra() for i, gp in enumerate(self._ir_grid_points): self._set_tetrahedra_frequencies(gp) for ib, frequencies in enumerate(self._tetrahedra_frequencies): self._tm.set_tetrahedra_omegas(frequencies) self._tm.run(self._frequency_points, value=value) iw = self._tm.get_integration_weight() self._integration_weights[:, ib, i] = iw self._integration_weights /= np.prod(self._mesh)
def _run_tetrahedron_method_dos(self): mesh_numbers = self._mesh_object.mesh_numbers cell = self._mesh_object.dynamical_matrix.primitive reciprocal_lattice = np.linalg.inv(cell.get_cell()) tm = TetrahedronMethod(reciprocal_lattice, mesh=mesh_numbers) self._dos = run_tetrahedron_method_dos( mesh_numbers, self._frequency_points, self._frequencies, self._mesh_object.grid_address, self._mesh_object.grid_mapping_table, tm.get_tetrahedra())
def _run_tetrahedron_method_dos(self): mesh = self._mesh_object.get_mesh_numbers() cell = self._mesh_object.get_dynamical_matrix().get_primitive() reciprocal_lattice = np.linalg.inv(cell.get_cell()) tm = TetrahedronMethod(reciprocal_lattice, mesh=mesh) self._dos = run_tetrahedron_method_dos( mesh, self._frequency_points, self._frequencies, self._mesh_object.get_grid_address(), self._mesh_object.get_grid_mapping_table(), tm.get_tetrahedra())
def _set_gamma_at_sigmas_lowmem(self, i): band_indices = self._pp.get_band_indices() (svecs, multiplicity, p2s, s2p, masses) = self._pp.get_primitive_and_supercell_correspondence() fc3 = self._pp.get_fc3() triplets_at_q, weights_at_q, _, _ = self._pp.get_triplets_at_q() bz_map = self._pp.get_bz_map() symmetrize_fc3_q = 0 reciprocal_lattice = np.linalg.inv(self._pp.get_primitive().get_cell()) thm = TetrahedronMethod(reciprocal_lattice, mesh=self._mesh) # It is assumed that self._sigmas = [None]. for j, sigma in enumerate(self._sigmas): self._collision.set_sigma(sigma) if self._is_N_U: collisions = np.zeros( (2, len(self._temperatures), len(band_indices)), dtype='double', order='C') else: collisions = np.zeros( (len(self._temperatures), len(band_indices)), dtype='double', order='C') import phono3py._phono3py as phono3c phono3c.pp_collision(collisions, thm.get_tetrahedra(), self._frequencies, self._eigenvectors, triplets_at_q, weights_at_q, self._grid_address, bz_map, self._mesh, fc3, svecs, multiplicity, masses, p2s, s2p, band_indices, self._temperatures, self._is_N_U * 1, symmetrize_fc3_q, self._cutoff_frequency) col_unit_conv = self._collision.get_unit_conversion_factor() pp_unit_conv = self._pp.get_unit_conversion_factor() if self._is_N_U: col = collisions.sum(axis=0) col_N = collisions[0] col_U = collisions[1] else: col = collisions for k in range(len(self._temperatures)): self._gamma[j, k, i, :] = average_by_degeneracy( col[k] * col_unit_conv * pp_unit_conv, band_indices, self._frequencies[self._grid_points[i]]) if self._is_N_U: self._gamma_N[j, k, i, :] = average_by_degeneracy( col_N[k] * col_unit_conv * pp_unit_conv, band_indices, self._frequencies[self._grid_points[i]]) self._gamma_U[j, k, i, :] = average_by_degeneracy( col_U[k] * col_unit_conv * pp_unit_conv, band_indices, self._frequencies[self._grid_points[i]])
def _run_tetrahedron_method_dos(self): mesh_numbers = self._mesh_object.mesh_numbers cell = self._mesh_object.dynamical_matrix.primitive reciprocal_lattice = np.linalg.inv(cell.get_cell()) tm = TetrahedronMethod(reciprocal_lattice, mesh=mesh_numbers) pdos = run_tetrahedron_method_dos( mesh_numbers, self._frequency_points, self._frequencies, self._mesh_object.grid_address, self._mesh_object.grid_mapping_table, tm.get_tetrahedra(), coef=self._eigvecs2) self._partial_dos = pdos.T
def _run_tetrahedron_method_dos(self): mesh = self._mesh_object.get_mesh_numbers() cell = self._mesh_object.get_dynamical_matrix().get_primitive() reciprocal_lattice = np.linalg.inv(cell.get_cell()) tm = TetrahedronMethod(reciprocal_lattice, mesh=mesh) pdos = run_tetrahedron_method_dos( mesh, self._frequency_points, self._frequencies, self._mesh_object.get_grid_address(), self._mesh_object.get_grid_mapping_table(), tm.get_tetrahedra(), coef=self._eigvecs2) self._partial_dos = pdos.T
def _set_integration_weights(self): primitive_lattice = np.linalg.inv(self._primitive.get_cell()) thm = TetrahedronMethod(primitive_lattice, mesh=self._mesh) num_grid_points = len(self._grid_points) num_band = self._primitive.get_number_of_atoms() * 3 self._integration_weights = np.zeros( (num_grid_points, len(self._band_indices), num_band), dtype='double') self._set_integration_weights_c(thm)
def get_unique_grid_points(grid_points, bz_grid): """Collect grid points on tetrahedron vertices around input grid points. Find grid points of 24 tetrahedra around each grid point and collect those grid points that are unique. Parameters ---------- grid_points : array_like Grid point indices. bz_grid : BZGrid Grid information in reciprocal space. Returns ------- ndarray Unique grid points on tetrahedron vertices around input grid points. shape=(unique_grid_points, ), dtype='int_'. """ import phono3py._phono3py as phono3c if _check_ndarray_state(grid_points, "int_"): _grid_points = grid_points else: _grid_points = np.array(grid_points, dtype="int_") thm = TetrahedronMethod(bz_grid.microzone_lattice) unique_vertices = np.array( np.dot(thm.get_unique_tetrahedra_vertices(), bz_grid.P.T), dtype="int_", order="C", ) neighboring_grid_points = np.zeros( len(unique_vertices) * len(_grid_points), dtype="int_" ) phono3c.neighboring_grid_points( neighboring_grid_points, _grid_points, unique_vertices, bz_grid.D_diag, bz_grid.addresses, bz_grid.gp_map, bz_grid.store_dense_gp_map * 1 + 1, ) unique_grid_points = np.array(np.unique(neighboring_grid_points), dtype="int_") return unique_grid_points
def set(self, value='I', division_number=201, frequency_points=None): self._grid_point_count = 0 self._value = value if frequency_points is None: max_frequency = np.amax(self._frequencies) min_frequency = np.amin(self._frequencies) self._frequency_points = np.linspace(min_frequency, max_frequency, division_number) else: self._frequency_points = frequency_points num_ir_grid_points = len(self._ir_grid_points) num_band = self._cell.get_number_of_atoms() * 3 num_freqs = len(self._frequency_points) self._integration_weights = np.zeros((num_freqs, num_band), dtype='double') reciprocal_lattice = np.linalg.inv(self._cell.get_cell()) self._tm = TetrahedronMethod(reciprocal_lattice, mesh=self._mesh) self._relative_grid_address = self._tm.get_tetrahedra()
def _run_c(self, lang='Py'): if self._sigma is None: self._tetrahedron_method = TetrahedronMethod( self._reciprocal_lattice, mesh=self._mesh) if lang == 'C': self._run_c_tetrahedron_method() else: self._run_py_tetrahedron_method() else: self._run_smearing_method()
def _set_triplets_integration_weights_c(g, g_zero, pp, frequency_points): import phono3py._phono3py as phono3c thm = TetrahedronMethod(pp.bz_grid.microzone_lattice) triplets_at_q = pp.get_triplets_at_q()[0] frequencies = pp.get_phonons()[0] phono3c.triplets_integration_weights( g, g_zero, frequency_points, # f0 np.array(np.dot(thm.get_tetrahedra(), pp.bz_grid.P.T), dtype="int_", order="C"), pp.bz_grid.D_diag, triplets_at_q, frequencies, # f1 frequencies, # f2 pp.bz_grid.addresses, pp.bz_grid.gp_map, pp.bz_grid.store_dense_gp_map * 1 + 1, g.shape[0], )
def _set_triplets_integration_weights_c(g, g_zero, interaction, frequency_points, neighboring_phonons=False): import phono3py._phono3py as phono3c reciprocal_lattice = np.linalg.inv(interaction.get_primitive().get_cell()) mesh = interaction.get_mesh_numbers() thm = TetrahedronMethod(reciprocal_lattice, mesh=mesh) grid_address = interaction.get_grid_address() bz_map = interaction.get_bz_map() triplets_at_q = interaction.get_triplets_at_q()[0] if neighboring_phonons: unique_vertices = thm.get_unique_tetrahedra_vertices() for i, j in zip((1, 2), (1, -1)): neighboring_grid_points = np.zeros( len(unique_vertices) * len(triplets_at_q), dtype=bz_map.dtype) phono3c.neighboring_grid_points( neighboring_grid_points, np.array(triplets_at_q[:, i], dtype='uintp').ravel(), j * unique_vertices, mesh, grid_address, bz_map) interaction.run_phonon_solver(np.unique(neighboring_grid_points)) frequencies = interaction.get_phonons()[0] phono3c.triplets_integration_weights( g, g_zero, frequency_points, # f0 thm.get_tetrahedra(), mesh, triplets_at_q, frequencies, # f1 frequencies, # f2 grid_address, bz_map, g.shape[0])
def tetrahedra_specify(self, lang="C"): reciprocal_lattice = np.linalg.inv(self._primitive.get_cell()) mesh = self._mesh if self._dim == 3: self._tetra = TetrahedronMethod(reciprocal_lattice, mesh=mesh) relative_address = self._tetra.get_tetrahedra() if lang == "C": self._unique_vertices = self.get_unique_tetrahedra_C( relative_address) else: self._unique_vertices = self.get_unique_tetrahedra_py( relative_address) elif self._dim == 2: self._tri = TriagonalMethod(reciprocal_lattice, mesh=mesh) relative_address = self._tri.get_triagonal() if lang == "C": self._unique_vertices = self.get_unique_triagonal_C( relative_address) else: self._unique_vertices = self.get_unique_triagonal_py( relative_address)
def set(self, value="I", division_number=201, frequency_points=None): """Prepare environment to peform linear tetrahedron method.""" self._grid_point_count = 0 self._value = value if frequency_points is None: max_frequency = np.amax(self._frequencies) min_frequency = np.amin(self._frequencies) self._frequency_points = np.linspace(min_frequency, max_frequency, division_number, dtype="double") else: self._frequency_points = np.array(frequency_points, dtype="double") num_band = self._frequencies.shape[1] num_freqs = len(self._frequency_points) self._integration_weights = np.zeros((num_freqs, num_band), dtype="double") reciprocal_lattice = np.linalg.inv(self._cell.cell) self._tm = TetrahedronMethod(reciprocal_lattice, mesh=self._mesh) self._relative_grid_address = self._tm.get_tetrahedra()
def test_SNF_tetrahedra_relative_grid(aln_lda): """Test relative grid addresses under GR-grid. Under GR-grid, grid point addressing becomes different from ordinal uniform grid. But P and Q matrices can be used to map betweewn these grid systems. In this test, the agreement is checked by representing them in Cartesian coordinates. """ lat = aln_lda.primitive.cell mesh = 25 for snf_coordinates, d_diag in zip(("direct", "reciprocal"), ([2, 8, 24], [1, 9, 45])): bzgrid = BZGrid( mesh, lattice=lat, symmetry_dataset=aln_lda.primitive_symmetry.dataset, use_grg=True, force_SNF=True, SNF_coordinates=snf_coordinates, ) np.testing.assert_equal(bzgrid.D_diag, d_diag) plat = np.linalg.inv(aln_lda.primitive.cell) mlat = bzgrid.microzone_lattice thm = TetrahedronMethod(mlat) snf_tetrahedra = np.dot(thm.get_tetrahedra(), bzgrid.P.T) for mtet, ptet in zip(thm.get_tetrahedra(), snf_tetrahedra): np.testing.assert_allclose( np.dot(mtet, mlat.T), np.dot(np.dot(ptet, bzgrid.QDinv.T), plat.T), atol=1e-8, )
def _set_integration_weights_py(self): if self._bz_grid.store_dense_gp_map: raise NotImplementedError("Only for type-I bz_map.") if self._bz_grid.grid_matrix is not None: raise NotImplementedError( "Generalized regular grid is not supported.") thm = TetrahedronMethod(self._bz_grid.microzone_lattice) num_grid_points = len(self._grid_points) num_band = len(self._primitive) * 3 self._integration_weights = np.zeros( (num_grid_points, len(self._band_indices), num_band), dtype="double") for i, gp in enumerate(self._grid_points): tfreqs = get_tetrahedra_frequencies( gp, self._bz_grid.D_diag, self._bz_grid.addresses, np.array( np.dot(thm.get_tetrahedra(), self._bz_grid.P.T), dtype="int_", order="C", ), self._grid_points, self._frequencies, grid_order=[ 1, self._bz_grid.D_diag[0], self._bz_grid.D_diag[0] * self._bz_grid.D_diag[1], ], lang="Py", ) for bi, frequencies in enumerate(tfreqs): thm.set_tetrahedra_omegas(frequencies) thm.run(self._frequencies[self._grid_point, self._band_indices]) iw = thm.get_integration_weight() self._integration_weights[i, :, bi] = iw
def _set_triplets_integration_weights_py(g, interaction, frequency_points): reciprocal_lattice = np.linalg.inv(interaction.get_primitive().get_cell()) mesh = interaction.get_mesh_numbers() thm = TetrahedronMethod(reciprocal_lattice, mesh=mesh) grid_address = interaction.get_grid_address() bz_map = interaction.get_bz_map() triplets_at_q = interaction.get_triplets_at_q()[0] unique_vertices = thm.get_unique_tetrahedra_vertices() tetrahedra_vertices = get_tetrahedra_vertices(thm.get_tetrahedra(), mesh, triplets_at_q, grid_address, bz_map) interaction.set_phonon(np.unique(tetrahedra_vertices)) frequencies = interaction.get_phonons()[0] num_band = frequencies.shape[1] for i, vertices in enumerate(tetrahedra_vertices): for j, k in list(np.ndindex((num_band, num_band))): f1_v = frequencies[vertices[0], j] f2_v = frequencies[vertices[1], k] thm.set_tetrahedra_omegas(f1_v + f2_v) thm.run(frequency_points) g0 = thm.get_integration_weight() g[0, i, :, j, k] = g0 thm.set_tetrahedra_omegas(-f1_v + f2_v) thm.run(frequency_points) g1 = thm.get_integration_weight() thm.set_tetrahedra_omegas(f1_v - f2_v) thm.run(frequency_points) g2 = thm.get_integration_weight() g[1, i, :, j, k] = g1 - g2 if len(g) == 3: g[2, i, :, j, k] = g0 + g1 + g2
class TetrahedronMesh(object): def __init__(self, cell, frequencies, # only at ir-grid-points mesh, grid_address, grid_mapping_table, ir_grid_points, grid_order=None, lang='C'): self._cell = cell self._frequencies = frequencies self._mesh = np.array(mesh, dtype='intc') self._grid_address = grid_address self._grid_mapping_table = grid_mapping_table self._lang = lang if lang == 'C': self._grid_order = None else: if grid_order is None: self._grid_order = [1, mesh[0], mesh[0] * mesh[1]] else: self._grid_order = grid_order self._ir_grid_points = ir_grid_points self._gp_ir_index = None self._tm = None self._tetrahedra_frequencies = None self._integration_weights = None self._relative_grid_address = None self._frequency_points = None self._value = None self._grid_point_count = 0 self._prepare() def __iter__(self): return self def __next__(self): if self._grid_point_count == len(self._ir_grid_points): raise StopIteration else: gp = self._ir_grid_points[self._grid_point_count] self._set_tetrahedra_frequencies(gp) for ib, frequencies in enumerate(self._tetrahedra_frequencies): self._tm.set_tetrahedra_omegas(frequencies) self._tm.run(self._frequency_points, value=self._value) iw = self._tm.get_integration_weight() self._integration_weights[:, ib] = iw self._integration_weights /= np.prod(self._mesh) self._grid_point_count += 1 return self._integration_weights def next(self): return self.__next__() def get_integration_weights(self): return self._integration_weights def get_frequency_points(self): return self._frequency_points def set(self, value='I', division_number=201, frequency_points=None): self._grid_point_count = 0 self._value = value if frequency_points is None: max_frequency = np.amax(self._frequencies) min_frequency = np.amin(self._frequencies) self._frequency_points = np.linspace(min_frequency, max_frequency, division_number) else: self._frequency_points = frequency_points num_ir_grid_points = len(self._ir_grid_points) num_band = self._cell.get_number_of_atoms() * 3 num_freqs = len(self._frequency_points) self._integration_weights = np.zeros((num_freqs, num_band), dtype='double') reciprocal_lattice = np.linalg.inv(self._cell.get_cell()) self._tm = TetrahedronMethod(reciprocal_lattice, mesh=self._mesh) self._relative_grid_address = self._tm.get_tetrahedra() def _prepare(self): ir_gp_indices = {} for i, gp in enumerate(self._ir_grid_points): ir_gp_indices[gp] = i self._gp_ir_index = np.zeros_like(self._grid_mapping_table) for i, gp in enumerate(self._grid_mapping_table): self._gp_ir_index[i] = ir_gp_indices[gp] def _set_tetrahedra_frequencies(self, gp): self._tetrahedra_frequencies = get_tetrahedra_frequencies( gp, self._mesh, self._grid_address, self._relative_grid_address, self._gp_ir_index, self._frequencies, grid_order=self._grid_order, lang=self._lang)
class TetrahedronMesh(object): def __init__(self, cell, frequencies, # only at ir-grid-points mesh, grid_address, grid_mapping_table, ir_grid_points, grid_order=None, lang='C'): """Linear tetrahedron method on uniform mesh for phonons Parameters ---------- cell : PhonopyAtoms Primitive cell used to calculate frequencies frequencies: ndarray Phonon frequences on grid points shape=(num_ir_grid_points, num_band) dtype='double' mesh : ndarray or list of int Mesh numbers for grids shape=(3,) dtype='intc' grid_address : ndarray Addresses of all grid points given by GridPoints class. shape=(prod(mesh), 3) dtype='intc' grid_mapping_table : ndarray Mapping of grid points to irreducible grid points given by GridPoints class. shape=(prod(mesh),) dtype='intc' ir_grid_points : ndarray Irreducible gird points given by GridPoints class. shape=(len(np.unique(grid_mapping_table)),) dtype='intc' grid_order : list of int, optional This controls how grid addresses are stored either C style or Fortran style. lang : str, 'C' or else, optional With 'C', C implementation is used. Otherwise Python implementation runs. """ self._cell = cell self._frequencies = frequencies self._mesh = np.array(mesh, dtype='intc') self._grid_address = grid_address self._grid_mapping_table = grid_mapping_table self._lang = lang if lang == 'C': self._grid_order = None else: if grid_order is None: self._grid_order = [1, mesh[0], mesh[0] * mesh[1]] else: self._grid_order = grid_order self._ir_grid_points = np.array(ir_grid_points, dtype='intc') self._gp_ir_index = None self._tm = None self._tetrahedra_frequencies = None self._integration_weights = None self._relative_grid_address = None self._frequency_points = None self._value = None self._grid_point_count = 0 self._prepare() def __iter__(self): return self def __next__(self): if self._grid_point_count == len(self._ir_grid_points): raise StopIteration else: gp = self._ir_grid_points[self._grid_point_count] self._set_tetrahedra_frequencies(gp) for ib, frequencies in enumerate(self._tetrahedra_frequencies): self._tm.set_tetrahedra_omegas(frequencies) self._tm.run(self._frequency_points, value=self._value) iw = self._tm.get_integration_weight() self._integration_weights[:, ib] = iw self._integration_weights /= np.prod(self._mesh) self._grid_point_count += 1 return self._integration_weights def next(self): return self.__next__() def get_integration_weights(self): return self._integration_weights def get_frequency_points(self): return self._frequency_points def set(self, value='I', division_number=201, frequency_points=None): self._grid_point_count = 0 self._value = value if frequency_points is None: max_frequency = np.amax(self._frequencies) min_frequency = np.amin(self._frequencies) self._frequency_points = np.linspace(min_frequency, max_frequency, division_number, dtype='double') else: self._frequency_points = np.array(frequency_points, dtype='double') num_band = self._cell.get_number_of_atoms() * 3 num_freqs = len(self._frequency_points) self._integration_weights = np.zeros((num_freqs, num_band), dtype='double') reciprocal_lattice = np.linalg.inv(self._cell.get_cell()) self._tm = TetrahedronMethod(reciprocal_lattice, mesh=self._mesh) self._relative_grid_address = self._tm.get_tetrahedra() def _prepare(self): ir_gp_indices = {} for i, gp in enumerate(self._ir_grid_points): ir_gp_indices[gp] = i self._gp_ir_index = np.zeros_like(self._grid_mapping_table) for i, gp in enumerate(self._grid_mapping_table): self._gp_ir_index[i] = ir_gp_indices[gp] def _set_tetrahedra_frequencies(self, gp): self._tetrahedra_frequencies = get_tetrahedra_frequencies( gp, self._mesh, self._grid_address, self._relative_grid_address, self._gp_ir_index, self._frequencies, grid_order=self._grid_order, lang=self._lang)
class JointDos: def __init__(self, mesh, primitive, supercell, fc2, nac_params=None, sigma=None, frequency_step=0.1, frequency_factor_to_THz=VaspToTHz, frequency_scale_factor=1.0, is_nosym=False, symprec=1e-5, filename=None, log_level=False, lapack_zheev_uplo='L'): self._grid_point = None self._mesh = np.array(mesh, dtype='intc') self._primitive = primitive self._supercell = supercell self._fc2 = fc2 self._nac_params = nac_params self.set_sigma(sigma) self._frequency_step = frequency_step self._frequency_factor_to_THz = frequency_factor_to_THz self._frequency_scale_factor = frequency_scale_factor self._is_nosym = is_nosym self._symprec = symprec self._filename = filename self._log_level = log_level self._lapack_zheev_uplo = lapack_zheev_uplo self._num_band = self._primitive.get_number_of_atoms() * 3 self._reciprocal_lattice = np.linalg.inv(self._primitive.get_cell()) self._set_dynamical_matrix() self._symmetry = Symmetry(primitive, symprec) self._tetrahedron_method = None self._phonon_done = None self._frequencies = None self._eigenvectors = None self._nac_q_direction = None self._joint_dos = None self._frequency_points = None def run(self): try: import anharmonic._phono3py as phono3c self._run_c() except ImportError: print "Joint density of states in python is not implemented." return None, None def get_joint_dos(self): return self._joint_dos def get_frequency_points(self): return self._frequency_points def get_phonons(self): return self._frequencies, self._eigenvectors, self._phonon_done def set_nac_q_direction(self, nac_q_direction=None): if nac_q_direction is not None: self._nac_q_direction = np.array(nac_q_direction, dtype='double') def set_sigma(self, sigma): if sigma is None: self._sigma = None else: self._sigma = float(sigma) def set_grid_point(self, grid_point): self._grid_point = grid_point self._set_triplets() num_grid = np.prod(len(self._grid_address)) num_band = self._num_band if self._phonon_done is None: self._phonon_done = np.zeros(num_grid, dtype='byte') self._frequencies = np.zeros((num_grid, num_band), dtype='double') self._eigenvectors = np.zeros((num_grid, num_band, num_band), dtype='complex128') self._joint_dos = [] self._frequency_points = [] self._set_phonon(np.array([grid_point], dtype='intc')) def get_grid_address(self): return self._grid_address def get_triplets_at_q(self): return self._triplets_at_q, self._weights_at_q def _run_c(self, lang='Py'): if self._sigma is None: self._tetrahedron_method = TetrahedronMethod( self._reciprocal_lattice, mesh=self._mesh) if lang == 'C': self._run_c_tetrahedron_method() else: self._run_py_tetrahedron_method() else: self._run_smearing_method() def _run_c_tetrahedron_method(self): """ This is not very faster than _run_c_tetrahedron_method and use much more memory space. So this function is not set as default. """ import anharmonic._phono3py as phono3c thm = self._tetrahedron_method unique_vertices = thm.get_unique_tetrahedra_vertices() for i, j in zip((1, 2), (1, -1)): neighboring_grid_points = np.zeros( len(unique_vertices) * len(self._triplets_at_q), dtype='intc') phono3c.neighboring_grid_points( neighboring_grid_points, self._triplets_at_q[:, i].flatten(), j * unique_vertices, self._mesh, self._grid_address, self._bz_map) self._set_phonon(np.unique(neighboring_grid_points)) f_max = np.max(self._frequencies) * 2 + self._frequency_step / 10 f_min = np.min(self._frequencies) * 2 frequency_points = np.arange(f_min, f_max, self._frequency_step, dtype='double') num_band = self._num_band num_triplets = len(self._triplets_at_q) num_freq_points = len(frequency_points) g = np.zeros((num_triplets, num_freq_points, num_band, num_band, 2), dtype='double') phono3c.triplets_integration_weights( g, frequency_points, thm.get_tetrahedra(), self._mesh, self._triplets_at_q, self._frequencies, self._grid_address, self._bz_map) jdos = np.tensordot(g, self._weights_at_q, axes=([0, 0])) jdos = jdos.sum(axis=1).sum(axis=1)[:, 0] self._joint_dos = jdos / np.prod(self._mesh) self._frequency_points = frequency_points def _run_py_tetrahedron_method(self): self._vertices = get_tetrahedra_vertices( self._tetrahedron_method.get_tetrahedra(), self._mesh, self._triplets_at_q, self._grid_address, self._bz_map) self._set_phonon(self._vertices.ravel()) thm = self._tetrahedron_method f_max = np.max(self._frequencies) * 2 + self._frequency_step / 10 f_min = np.min(self._frequencies) * 2 freq_points = np.arange(f_min, f_max, self._frequency_step, dtype='double') jdos = np.zeros_like(freq_points) for vertices, w in zip(self._vertices, self._weights_at_q): for i, j in list(np.ndindex(self._num_band, self._num_band)): f1 = self._frequencies[vertices[0], i] f2 = self._frequencies[vertices[1], j] thm.set_tetrahedra_omegas(f1 + f2) thm.run(freq_points) iw = thm.get_integration_weight() jdos += iw * w self._joint_dos = jdos / np.prod(self._mesh) self._frequency_points = freq_points def _run_smearing_method(self): import anharmonic._phono3py as phono3c self._set_phonon(self._triplets_at_q.ravel()) f_max = np.max(self._frequencies) * 2 + self._sigma * 4 f_min = np.min(self._frequencies) * 2 - self._sigma * 4 freq_points = np.arange(f_min, f_max, self._frequency_step, dtype='double') jdos = np.zeros_like(freq_points) phono3c.joint_dos(jdos, freq_points, self._triplets_at_q, self._weights_at_q, self._frequencies, self._sigma) jdos /= np.prod(self._mesh) self._joint_dos = jdos self._frequency_points = freq_points def _set_dynamical_matrix(self): self._dm = get_dynamical_matrix( self._fc2, self._supercell, self._primitive, nac_params=self._nac_params, frequency_scale_factor=self._frequency_scale_factor, symprec=self._symprec) def _set_triplets(self): if self._is_nosym: if self._log_level: print "Triplets at q without considering symmetry" sys.stdout.flush() (self._triplets_at_q, self._weights_at_q, self._grid_address, self._bz_map) = get_nosym_triplets_at_q( self._grid_point, self._mesh, self._reciprocal_lattice, with_bz_map=True) else: (self._triplets_at_q, self._weights_at_q, self._grid_address, self._bz_map) = get_triplets_at_q( self._grid_point, self._mesh, self._symmetry.get_pointgroup_operations(), self._reciprocal_lattice) def _set_phonon(self, grid_points): set_phonon_c(self._dm, self._frequencies, self._eigenvectors, self._phonon_done, grid_points, self._grid_address, self._mesh, self._frequency_factor_to_THz, self._nac_q_direction, self._lapack_zheev_uplo)
class TetrahedronMesh: def __init__(self, mesh_object): self._mesh_object = mesh_object self._grid_address = None self._grid_order = None self._ir_grid_points = None self._ir_grid_weights = None self._gp_ir_index = None self._cell = None self._frequencies = None self._eigenvalues = None self._eigenvectors = None self._tm = None self._tetrahedra_frequencies = None self._integration_weights = None self._relative_grid_address = None self._total_dos = None self._partial_dos = None self._prepare() def get_total_dos(self): return self._total_dos def get_partial_dos(self): return self._partial_dos def get_integration_weights(self): return self._integration_weights def get_frequency_points(self): return self._frequency_points def run_at_frequencies(self, value='I', division_number=201, frequency_points=None): if frequency_points is None: max_frequency = np.amax(self._frequencies) min_frequency = np.amin(self._frequencies) self._frequency_points = np.linspace(min_frequency, max_frequency, division_number) else: self._frequency_points = frequency_points num_ir_grid_points = len(self._ir_grid_points) num_band = self._cell.get_number_of_atoms() * 3 num_freqs = len(self._frequency_points) self._integration_weights = np.zeros( (num_freqs, num_band, num_ir_grid_points), dtype='double') reciprocal_lattice = np.linalg.inv(self._cell.get_cell()) self._tm = TetrahedronMethod(reciprocal_lattice, mesh=self._mesh) self._relative_grid_address = self._tm.get_tetrahedra() for i, gp in enumerate(self._ir_grid_points): self._set_tetrahedra_frequencies(gp) for ib, frequencies in enumerate(self._tetrahedra_frequencies): self._tm.set_tetrahedra_omegas(frequencies) self._tm.run(self._frequency_points, value=value) iw = self._tm.get_integration_weight() self._integration_weights[:, ib, i] = iw self._integration_weights /= np.prod(self._mesh) def _prepare(self): mo = self._mesh_object self._cell = mo.get_dynamical_matrix().get_primitive() self._mesh = mo.get_mesh_numbers() self._grid_address = mo.get_grid_address() self._ir_grid_points = mo.get_ir_grid_points() self._ir_grid_weights = mo.get_weights() self._grid_order = [1, self._mesh[0], self._mesh[0] * self._mesh[1]] grid_mapping_table = mo.get_grid_mapping_table() self._gp_ir_index = np.zeros_like(grid_mapping_table) count = 0 for i, gp in enumerate(grid_mapping_table): if i == gp: self._gp_ir_index[i] = count count += 1 else: self._gp_ir_index[i] = self._gp_ir_index[grid_mapping_table[i]] self._frequencies = mo.get_frequencies() self._eigenvectors = mo.get_eigenvectors() def _set_tetrahedra_frequencies(self, gp): self._tetrahedra_frequencies = get_tetrahedra_frequencies( gp, self._mesh, self._grid_order, self._grid_address, self._relative_grid_address, self._gp_ir_index, self._frequencies)
class TetrahedronMesh: def __init__( self, cell, frequencies, # only at ir-grid-points mesh, grid_address, grid_mapping_table, grid_order=None): self._cell = cell self._frequencies = frequencies self._mesh = mesh self._grid_address = grid_address self._grid_mapping_table = grid_mapping_table if grid_order is None: self._grid_order = [1, mesh[0], mesh[0] * mesh[1]] else: self._grid_order = grid_order self._ir_grid_points = None self._gp_ir_index = None self._tm = None self._tetrahedra_frequencies = None self._integration_weights = None self._relative_grid_address = None self._prepare() def get_integration_weights(self): return self._integration_weights def get_frequency_points(self): return self._frequency_points def run_at_frequencies(self, value='I', division_number=201, frequency_points=None): if frequency_points is None: max_frequency = np.amax(self._frequencies) min_frequency = np.amin(self._frequencies) self._frequency_points = np.linspace(min_frequency, max_frequency, division_number) else: self._frequency_points = frequency_points num_ir_grid_points = len(self._ir_grid_points) num_band = self._cell.get_number_of_atoms() * 3 num_freqs = len(self._frequency_points) self._integration_weights = np.zeros( (num_freqs, num_band, num_ir_grid_points), dtype='double') reciprocal_lattice = np.linalg.inv(self._cell.get_cell()) self._tm = TetrahedronMethod(reciprocal_lattice, mesh=self._mesh) self._relative_grid_address = self._tm.get_tetrahedra() for i, gp in enumerate(self._ir_grid_points): self._set_tetrahedra_frequencies(gp) for ib, frequencies in enumerate(self._tetrahedra_frequencies): self._tm.set_tetrahedra_omegas(frequencies) self._tm.run(self._frequency_points, value=value) iw = self._tm.get_integration_weight() self._integration_weights[:, ib, i] = iw self._integration_weights /= np.prod(self._mesh) def _prepare(self): (self._ir_grid_points, ir_grid_weights) = extract_ir_grid_points(self._grid_mapping_table) ir_gp_indices = {} for i, gp in enumerate(self._ir_grid_points): ir_gp_indices[gp] = i self._gp_ir_index = np.zeros_like(self._grid_mapping_table) for i, gp in enumerate(self._grid_mapping_table): self._gp_ir_index[i] = ir_gp_indices[gp] def _set_tetrahedra_frequencies(self, gp): self._tetrahedra_frequencies = get_tetrahedra_frequencies( gp, self._mesh, self._grid_order, self._grid_address, self._relative_grid_address, self._gp_ir_index, self._frequencies)
class TetrahedronMesh(object): def __init__(self, cell, frequencies, # only at ir-grid-points mesh, grid_address, grid_mapping_table, ir_grid_points, grid_order=None, lang='C'): """Linear tetrahedron method on uniform mesh for phonons Parameters ---------- cell : PhonopyAtoms Primitive cell used to calculate frequencies frequencies: ndarray Phonon frequences on grid points shape=(num_ir_grid_points, num_band) dtype='double' mesh : ndarray or list of int Mesh numbers for grids shape=(3,) dtype='intc' grid_address : ndarray Addresses of all grid points given by GridPoints class. shape=(prod(mesh), 3) dtype='intc' grid_mapping_table : ndarray Mapping of grid points to irreducible grid points given by GridPoints class. shape=(prod(mesh),) dtype='uintp' ir_grid_points : ndarray Irreducible gird points given by GridPoints class. shape=(len(np.unique(grid_mapping_table)),) dtype='uintp' grid_order : list of int, optional This controls how grid addresses are stored either C style or Fortran style. lang : str, 'C' or else, optional With 'C', C implementation is used. Otherwise Python implementation runs. """ self._cell = cell self._frequencies = frequencies self._mesh = np.array(mesh, dtype='intc') self._grid_address = grid_address self._grid_mapping_table = grid_mapping_table self._lang = lang if lang == 'C': self._grid_order = None else: if grid_order is None: self._grid_order = [1, mesh[0], mesh[0] * mesh[1]] else: self._grid_order = grid_order self._ir_grid_points = ir_grid_points self._gp_ir_index = None self._tm = None self._tetrahedra_frequencies = None self._integration_weights = None self._relative_grid_address = None self._frequency_points = None self._value = None self._grid_point_count = 0 self._prepare() def __iter__(self): return self def __next__(self): if self._grid_point_count == len(self._ir_grid_points): raise StopIteration else: gp = self._ir_grid_points[self._grid_point_count] self._set_tetrahedra_frequencies(gp) for ib, frequencies in enumerate(self._tetrahedra_frequencies): self._tm.set_tetrahedra_omegas(frequencies) self._tm.run(self._frequency_points, value=self._value) iw = self._tm.get_integration_weight() self._integration_weights[:, ib] = iw self._integration_weights /= np.prod(self._mesh) self._grid_point_count += 1 return self._integration_weights def next(self): return self.__next__() def get_integration_weights(self): return self._integration_weights def get_frequency_points(self): return self._frequency_points def set(self, value='I', division_number=201, frequency_points=None): self._grid_point_count = 0 self._value = value if frequency_points is None: max_frequency = np.amax(self._frequencies) min_frequency = np.amin(self._frequencies) self._frequency_points = np.linspace(min_frequency, max_frequency, division_number, dtype='double') else: self._frequency_points = np.array(frequency_points, dtype='double') num_band = self._cell.get_number_of_atoms() * 3 num_freqs = len(self._frequency_points) self._integration_weights = np.zeros((num_freqs, num_band), dtype='double') reciprocal_lattice = np.linalg.inv(self._cell.get_cell()) self._tm = TetrahedronMethod(reciprocal_lattice, mesh=self._mesh) self._relative_grid_address = self._tm.get_tetrahedra() def _prepare(self): ir_gp_indices = {} for i, gp in enumerate(self._ir_grid_points): ir_gp_indices[gp] = i self._gp_ir_index = np.zeros_like(self._grid_mapping_table) for i, gp in enumerate(self._grid_mapping_table): self._gp_ir_index[i] = ir_gp_indices[gp] def _set_tetrahedra_frequencies(self, gp): self._tetrahedra_frequencies = get_tetrahedra_frequencies( gp, self._mesh, self._grid_address, self._relative_grid_address, self._gp_ir_index, self._frequencies, grid_order=self._grid_order, lang=self._lang)
def _run_py_tetrahedron_method(self): thm = TetrahedronMethod(self._reciprocal_lattice, mesh=self._mesh) self._vertices = get_tetrahedra_vertices(thm.get_tetrahedra(), self._mesh, self._triplets_at_q, self._grid_address, self._bz_map) self.run_phonon_solver(self._vertices.ravel()) f_max = np.max(self._frequencies) * 2 f_max *= 1.005 f_min = 0 self._set_uniform_frequency_points(f_min, f_max) num_freq_points = len(self._frequency_points) jdos = np.zeros((num_freq_points, 2), dtype='double') for vertices, w in zip(self._vertices, self._weights_at_q): for i, j in list(np.ndindex(self._num_band, self._num_band)): f1 = self._frequencies[vertices[0], i] f2 = self._frequencies[vertices[1], j] thm.set_tetrahedra_omegas(f1 + f2) thm.run(self._frequency_points) iw = thm.get_integration_weight() jdos[:, 1] += iw * w thm.set_tetrahedra_omegas(f1 - f2) thm.run(self._frequency_points) iw = thm.get_integration_weight() jdos[:, 0] += iw * w thm.set_tetrahedra_omegas(-f1 + f2) thm.run(self._frequency_points) iw = thm.get_integration_weight() jdos[:, 0] += iw * w self._joint_dos = jdos / np.prod(self._mesh)
def _set_triplets_integration_weights_c(g, interaction, frequency_points = None, neighboring_phonons=True, triplets_at_q=None, band_indices=None, is_triplet_symmetry=False): import anharmonic._phono3py as phono3c if triplets_at_q == None: triplets_at_q = interaction.get_triplets_at_q()[0] if len(triplets_at_q) == 0: return reciprocal_lattice = np.linalg.inv(interaction.get_primitive().get_cell()) mesh = interaction.get_mesh_numbers() thm = TetrahedronMethod(reciprocal_lattice, mesh=mesh) grid_address = interaction.get_grid_address() bz_map = interaction.get_bz_map() if neighboring_phonons: unique_vertices = thm.get_unique_tetrahedra_vertices() for i in (1, 2, 0): # index inside a triplet for j in (1, -1): neighboring_grid_points = np.zeros( len(unique_vertices) * len(np.unique(triplets_at_q[:, i])), dtype='intc') phono3c.neighboring_grid_points( neighboring_grid_points, np.unique(triplets_at_q[:, i]).astype("intc"), j * unique_vertices, mesh, grid_address, bz_map) interaction.set_phonons(np.unique(neighboring_grid_points)) frequencies = interaction.get_phonons()[0] if len(np.where(mesh == 1)[0]) < 2: if band_indices is None: phono3c.triplets_integration_weights_fpoints( g, frequency_points, thm.get_tetrahedra().astype("intc").copy(), mesh, triplets_at_q, frequencies, grid_address, bz_map) else: phono3c.triplets_integration_weights( g, thm.get_tetrahedra().astype("intc").copy(), mesh, triplets_at_q, frequencies, np.array(band_indices, dtype='intc'), grid_address, bz_map, is_triplet_symmetry) else: # 1D case possible_shift = np.array((np.array(mesh) != 1), dtype='intc') relative_address = np.array([[[0, 0, 0], possible_shift], [[0, 0, 0], -possible_shift]], dtype="intc") if band_indices is None: phono3c.triplets_integration_weights_1D_fpoints( g, frequency_points, relative_address, mesh, triplets_at_q, frequencies, grid_address, bz_map) else: phono3c.triplets_integration_weights_1D( g, relative_address, mesh, triplets_at_q, frequencies, np.array(band_indices, dtype='intc'), grid_address, bz_map, is_triplet_symmetry)
class Conductivity: def __init__( self, interaction, symmetry, grid_points=None, temperatures=np.arange(0, 1001, 10, dtype='double'), sigmas=[], is_isotope=False, mass_variances=None, mesh_divisors=None, coarse_mesh_shifts=None, boundary_mfp=None, # in micrometre no_kappa_stars=False, gv_delta_q=None, # finite difference for group veolocity log_level=0, is_band_connection=True, write_tecplot=False): self._pp = interaction self._collision = None # has to be set derived class self._no_kappa_stars = no_kappa_stars self._gv_delta_q = gv_delta_q self._log_level = log_level self._sigmas = sigmas self._temperatures = temperatures self._primitive = self._pp.get_primitive() self._dm = self._pp.get_dynamical_matrix() self._frequency_factor_to_THz = self._pp.get_frequency_factor_to_THz() self._cutoff_frequency = self._pp.get_cutoff_frequency() self._boundary_mfp = boundary_mfp self._write_tecplot = write_tecplot self._set_mesh_numbers(mesh_divisors=mesh_divisors, coarse_mesh_shifts=coarse_mesh_shifts) if (np.array(self._mesh) == 1).sum() > 1: if is_band_connection: interaction.set_phonons_all( is_band_connection=is_band_connection) self._symmetry = symmetry self._bz_grid_address = None self._bz_to_pp_map = None self._coarse_mesh_shifts = None if self._no_kappa_stars: self._kpoint_operations = np.array([np.eye(3)], dtype="intc") self._mappings = np.arange(np.prod(self._mesh)) self._rot_mappings = np.zeros(len(self._mappings), dtype="intc") else: self._kpoint_operations = get_kpoint_group( self._mesh, self._pp.get_point_group_operations()) (self._mappings, self._rot_mappings) = get_mappings( self._mesh, self._pp.get_point_group_operations(), qpoints=np.array([0, 0, 0], dtype="double")) self._kpoint_group_sum_map = get_group_summation( self._kpoint_operations) self._kpoint_group_inv_map = get_group_inversion( self._kpoint_operations) rec_lat = np.linalg.inv(self._primitive.get_cell()) self._rotations_cartesian = np.array([ similarity_transformation(rec_lat, r) for r in self._kpoint_operations ], dtype='double') self._grid_points = None self._grid_weights = None self._grid_address = None self._ir_grid_points = None self._ir_grid_weights = None self._kappa = None self._kappa0 = None self._mode_kappa = None self._gamma = None self._read_gamma = False self._read_gamma_iso = False self._frequencies = None self._eigen_vectors = None self._gv = None self._gamma_iso = None volume = self._primitive.get_volume() self._conversion_factor = unit_to_WmK / volume self._kappa_factor = ite_unit_to_WmK / volume self._irr_index_mapping = np.where( np.unique(self._mappings) - self._mappings.reshape(-1, 1) == 0)[1] self._isotope = None self._mass_variances = None self._is_isotope = is_isotope if mass_variances is not None: self._is_isotope = True if self._is_isotope: self._set_isotope(mass_variances) self._grid_point_count = None self._degeneracies = None self._set_grid_properties(grid_points) self._bz_to_pp_map = self._pp.get_bz_to_pp_map() def get_mesh_divisors(self): return self._mesh_divisors def get_mesh_numbers(self): return self._mesh def get_group_velocities(self): return self._gv def get_mode_heat_capacities(self): pass def get_frequencies(self): return self._frequencies[self._grid_points] def get_qpoints(self): return self._qpoints def get_grid_points(self): return self._grid_points def get_grid_weights(self): return self._grid_weights def get_temperatures(self): return self._temperatures def set_temperature(self, i, temperature=None): self._itemp = i if self._temperatures is not None: self._temp = self._temperatures[i] else: self._temp = temperature def set_sigma(self, s, sigma=None): self._isigma = s if self._sigmas is not None: self._sigma = self._sigmas[s] else: self._sigma = sigma def set_temperatures(self, temperatures): self._temperatures = temperatures self._allocate_values() def set_gamma(self, gamma): self._gamma = gamma self._read_gamma = True def set_gamma_isotope(self, gamma_iso): self._gamma_iso = gamma_iso self._read_gamma_iso = True def get_gamma(self): return self._gamma def get_gamma_isotope(self): return self._gamma_iso def get_kappa(self): return self._kappa def get_kappa0(self): return self._kappa0 def get_mode_kappa(self): return self._mode_kappa def get_sigmas(self): return self._sigmas def get_grid_point_count(self): return self._grid_point_count def set_pp_grid_points_all(self): self._pp.set_grid_points(self._grid_points) def _run_at_grid_point(self): """This has to be implemented in the derived class""" pass def _allocate_values(self): """This has to be implemented in the derived class""" pass def _calculate_kappa(self): """This has to be implemented in the derived class""" pass def _get_cv(self, freqs): cv = np.zeros((len(self._temperatures), len(freqs)), dtype='double') # T/freq has to be large enough to avoid divergence. # Otherwise just set 0. for i, f in enumerate(freqs): finite_t = (self._temperatures > f / 100) if f > self._cutoff_frequency: cv[:, i] = np.where( finite_t, get_mode_cv(np.where(finite_t, self._temperatures, 10000), f * THzToEv), 0) return cv def set_rot_grid_points(self): num_rot = len(self._kpoint_operations) num_mesh_points = np.prod(self._mesh) self._rot_grid_points = np.zeros((num_rot, num_mesh_points), dtype='intc') for i in range(num_mesh_points): self._rot_grid_points[:, i] = get_grid_points_by_rotations( self._grid_address[i], self._kpoint_operations, self._mesh) def _set_grid_properties(self, grid_points): self._grid_address = self._pp.get_grid_address() if grid_points is not None: # Specify grid points self._grid_points = reduce_grid_points( self._mesh_divisors, self._grid_address, grid_points, coarse_mesh_shifts=self._coarse_mesh_shifts) (self._ir_grid_points, self._ir_grid_weights) = self._get_ir_grid_points() elif self._no_kappa_stars: # All grid points coarse_grid_address = get_grid_address(self._coarse_mesh) coarse_grid_points = np.arange(np.prod(self._coarse_mesh), dtype='intc') self._grid_points = from_coarse_to_dense_grid_points( self._mesh, self._mesh_divisors, coarse_grid_points, coarse_grid_address, coarse_mesh_shifts=self._coarse_mesh_shifts) self._grid_weights = np.ones(len(self._grid_points), dtype='intc') self._ir_grid_points = self._grid_points self._ir_grid_weights = self._grid_weights else: # Automatic sampling self._grid_points, self._grid_weights = self._get_ir_grid_points() self._ir_grid_points = self._grid_points self._ir_grid_weights = self._grid_weights self._qpoints = np.array(self._grid_address[self._grid_points] / self._mesh.astype('double'), dtype='double', order='C') self._grid_point_count = 0 self._pp.set_phonons(self._grid_points) self._frequencies = self._pp.get_phonons()[0][self._grid_points] self._eigen_vectors = self._pp.get_phonons()[1][self._grid_points] self._degeneracies = self._pp.get_degeneracy()[self._grid_points] if self._write_tecplot: self._dim = np.count_nonzero(np.array(self._mesh) > 1) #only dim=2 or 3 are implemented assert self._dim > 1, "The dimention of the given system is %d, but only dim=2 or 3 are implemented" % self._dim self.set_bz_grid_points() self.tetrahedra_specify() def _set_gamma_isotope_at_sigmas(self, i): for j, sigma in enumerate(self._sigmas): if self._log_level: print "Calculating Gamma of ph-isotope with", if sigma is None: print "tetrahedron method" else: print "sigma=%s" % sigma pp_freqs, pp_eigvecs, pp_phonon_done = self._pp.get_phonons() self._isotope.set_sigma(sigma) self._isotope.set_phonons(pp_freqs, pp_eigvecs, pp_phonon_done, dm=self._dm) gp = self._grid_points[i] self._isotope.set_grid_point(gp) self._isotope.run() self._gamma_iso[j, i] = self._isotope.get_gamma() def _set_mesh_numbers(self, mesh_divisors=None, coarse_mesh_shifts=None): self._mesh = self._pp.get_mesh_numbers() if mesh_divisors is None: self._mesh_divisors = np.array([1, 1, 1], dtype='intc') else: self._mesh_divisors = [] for i, (m, n) in enumerate(zip(self._mesh, mesh_divisors)): if m % n == 0: self._mesh_divisors.append(n) else: self._mesh_divisors.append(1) print("Mesh number %d for the " + ["first", "second", "third"][i] + " axis is not dividable by divisor %d.") % (m, n) self._mesh_divisors = np.array(self._mesh_divisors, dtype='intc') if coarse_mesh_shifts is None: self._coarse_mesh_shifts = [False, False, False] else: self._coarse_mesh_shifts = coarse_mesh_shifts for i in range(3): if (self._coarse_mesh_shifts[i] and (self._mesh_divisors[i] % 2 != 0)): print("Coarse grid along " + ["first", "second", "third"][i] + " axis can not be shifted. Set False.") self._coarse_mesh_shifts[i] = False self._coarse_mesh = self._mesh / self._mesh_divisors if self._log_level: print("Lifetime sampling mesh: [ %d %d %d ]" % tuple(self._mesh / self._mesh_divisors)) def _get_ir_grid_points(self): if self._coarse_mesh_shifts is None: mesh_shifts = [False, False, False] else: mesh_shifts = self._coarse_mesh_shifts (coarse_grid_points, coarse_grid_weights, coarse_grid_address) = get_ir_grid_points(self._coarse_mesh, self._primitive, mesh_shifts=mesh_shifts) grid_points = from_coarse_to_dense_grid_points( self._mesh, self._mesh_divisors, coarse_grid_points, coarse_grid_address, coarse_mesh_shifts=self._coarse_mesh_shifts) grid_weights = coarse_grid_weights assert grid_weights.sum() == np.prod(self._mesh / self._mesh_divisors) return grid_points, grid_weights def set_bz_grid_points(self): self._bz_grid_address, self._bz_map , self._bz_to_pp_map= \ relocate_BZ_grid_address(self._grid_address, self._mesh, np.linalg.inv(self._primitive.get_cell()), is_bz_map_to_orig=True) def tetrahedra_specify(self, lang="C"): reciprocal_lattice = np.linalg.inv(self._primitive.get_cell()) mesh = self._mesh if self._dim == 3: self._tetra = TetrahedronMethod(reciprocal_lattice, mesh=mesh) relative_address = self._tetra.get_tetrahedra() if lang == "C": self._unique_vertices = self.get_unique_tetrahedra_C( relative_address) else: self._unique_vertices = self.get_unique_tetrahedra_py( relative_address) elif self._dim == 2: self._tri = TriagonalMethod(reciprocal_lattice, mesh=mesh) relative_address = self._tri.get_triagonal() if lang == "C": self._unique_vertices = self.get_unique_triagonal_C( relative_address) else: self._unique_vertices = self.get_unique_triagonal_py( relative_address) def _set_isotope(self, mass_variances): if mass_variances is True: mv = None else: mv = mass_variances self._isotope = CollisionIso( self._mesh, self._primitive, mass_variances=mv, frequency_factor_to_THz=self._frequency_factor_to_THz, symprec=self._symmetry.get_symmetry_tolerance(), cutoff_frequency=self._cutoff_frequency, lapack_zheev_uplo=self._pp.get_lapack_zheev_uplo()) self._mass_variances = self._isotope.get_mass_variances() def _set_gv(self, i): # Group velocity [num_freqs, 3] phonon = (self._frequencies[i], self._eigen_vectors[i], self._degeneracies[i]) gv = self._get_gv(self._qpoints[i], phonon=phonon) self._gv[i] = gv # if self._degeneracies is not None: # deg = self._degeneracies[i] # self._gv[i] = get_degenerate_property(deg, gv) def _get_gv(self, q, phonon=None): return get_group_velocity( q, self._dm, symmetry=self._symmetry, q_length=self._gv_delta_q, phonon=phonon, frequency_factor_to_THz=self._frequency_factor_to_THz) def _get_main_diagonal(self, i, j, k): num_band = self._primitive.get_number_of_atoms() * 3 main_diagonal = self._gamma[j, k, i].copy() if self._gamma_iso is not None: main_diagonal += self._gamma_iso[j, i] if self._boundary_mfp is not None: main_diagonal += self._get_boundary_scattering(i) # if self._boundary_mfp is not None: # for l in range(num_band): # # Acoustic modes at Gamma are avoided. # if i == 0 and l < 3: # continue # gv_norm = np.linalg.norm(self._gv[i, l]) # mean_free_path = (gv_norm * Angstrom * 1e6 / # (4 * np.pi * main_diagonal[l])) # if mean_free_path > self._boundary_mfp: # main_diagonal[l] = ( # gv_norm / (4 * np.pi * self._boundary_mfp)) return main_diagonal def _get_boundary_scattering(self, i): num_band = self._primitive.get_number_of_atoms() * 3 g_boundary = np.zeros(num_band, dtype='double') for l in range(num_band): g_boundary[l] = (np.linalg.norm(self._gv[i, l]) * Angstrom * 1e6 / (4 * np.pi * self._boundary_mfp)) return g_boundary def _show_log_header(self, i): if self._log_level: gp = self._grid_points[i] print( "======================= Grid point %d (%d/%d) " "=======================" % (gp, i + 1, len(self._grid_points))) print "q-point: (%5.2f %5.2f %5.2f)" % tuple(self._qpoints[i]) if self._boundary_mfp is not None: if self._boundary_mfp > 1000: print("Boundary mean free path (millimetre): %.3f" % (self._boundary_mfp / 1000.0)) else: print("Boundary mean free path (micrometre): %.5f" % self._boundary_mfp) if self._is_isotope: print "Mass variance parameters:", print("%5.2e " * len(self._mass_variances)) % tuple( self._mass_variances) def get_unique_tetrahedra_C(self, relative_address): import phonopy._spglib as spg num_expect = np.prod(self._mesh) * 6 unique_vertices = np.zeros((num_expect, 4), dtype="intc") number_of_unique = spg.unique_tetrahedra(unique_vertices, self._bz_grid_address, self._bz_map, relative_address, self._mesh) return unique_vertices[:number_of_unique] def get_unique_triagonal_C(self, relative_address): import phonopy._spglib as spg num_expect = np.prod(self._mesh) * 6 unique_vertices = np.zeros((num_expect, 3), dtype="intc") number_of_unique = spg.unique_tetrahedra(unique_vertices, self._bz_grid_address, self._bz_map, relative_address, self._mesh) return unique_vertices[:number_of_unique] def get_unique_triagonal_py(self, relative_address): assert np.count_nonzero(self._mesh > 1) == 2 # bzmesh = np.extract(self._mesh>1, self._mesh) * 2 bzmesh = self._mesh * 2 bz_grid_order = [1, bzmesh[0], bzmesh[0] * bzmesh[1]] num_grids = len(self._bz_grid_address) unique_vertices = [] for i in np.arange(num_grids): adrs = self._bz_grid_address[i] + relative_address bz_gp = np.dot(adrs % bzmesh, bz_grid_order) vgp = self._bz_map[bz_gp] for triag in vgp: if (triag == -1).any(): continue exists = False for element in unique_vertices: if (triag == element).all(): exists = True break if not exists: unique_vertices.append(triag) return np.array(unique_vertices) def get_unique_tetrahedra_py(self, relative_address): bzmesh = self._mesh * 2 bz_grid_order = [1, bzmesh[0], bzmesh[0] * bzmesh[1]] num_grids = len(self._bz_grid_address) unique_vertices = [] for i in np.arange(num_grids): adrs = self._bz_grid_address[i] + relative_address bz_gp = np.dot(adrs % bzmesh, bz_grid_order) vgp = self._bz_map[bz_gp] for tetra in vgp: if (tetra == -1).any(): continue exists = False for element in unique_vertices: if (tetra == element).all(): exists = True break if not exists: unique_vertices.append(tetra) return np.array(unique_vertices) def print_kappa(self, isigma=None, itemp=None): temperatures = self._temperatures directions = ['xx', 'yy', 'zz', 'xy', 'yz', 'zx'] if self._log_level == 0: directions = self._kappa if self._log_level == 2: directions = directions if self._log_level == 0: directions = np.argmax(self._kappa, axis=-1) if self._log_level == 1: directions = ['xx', 'yy', 'zz'] for i, sigma in enumerate(self._sigmas): if isigma is not None: if i != isigma: continue kappa = self._kappa[i] band = ['band' + str(b + 1) for b in range(kappa.shape[2])] print "----------- Thermal conductivity (W/m-k) for", print "sigma=%s -----------" % sigma for j, direction in enumerate(directions): print "*direction:%s" % direction print("#%6s%10s" + " %9s" * len(band)) % ( ("T(K)", "Total") + tuple(band)) for m, (t, k) in enumerate( zip(temperatures, kappa[..., j].sum(axis=0))): if itemp is not None: if m != itemp: continue print("%7.1f%10.3f" + " %9.3f" * len(band)) % ( (t, k.sum()) + tuple(k)) print sys.stdout.flush()
def _set_gamma_at_sigmas_lowmem(self, i): """Calculate gamma without storing ph-ph interaction strength. `svecs` and `multi` below must not be simply replaced by `self._pp.primitive.get_smallest_vectors()` because they must be in dense format as always so in Interaction class instance. `p2s`, `s2p`, and `masses` have to be also given from Interaction class instance. """ band_indices = self._pp.band_indices ( svecs, multi, p2s, s2p, masses, ) = self._pp.get_primitive_and_supercell_correspondence() fc3 = self._pp.fc3 triplets_at_q, weights_at_q, _, _ = self._pp.get_triplets_at_q() symmetrize_fc3_q = 0 if None in self._sigmas: thm = TetrahedronMethod(self._pp.bz_grid.microzone_lattice) # It is assumed that self._sigmas = [None]. for j, sigma in enumerate(self._sigmas): self._collision.set_sigma(sigma) if self._is_N_U: collisions = np.zeros( (2, len(self._temperatures), len(band_indices)), dtype="double", order="C", ) else: collisions = np.zeros( (len(self._temperatures), len(band_indices)), dtype="double", order="C", ) import phono3py._phono3py as phono3c if sigma is None: phono3c.pp_collision( collisions, np.array( np.dot(thm.get_tetrahedra(), self._pp.bz_grid.P.T), dtype="int_", order="C", ), self._frequencies, self._eigenvectors, triplets_at_q, weights_at_q, self._pp.bz_grid.addresses, self._pp.bz_grid.gp_map, self._pp.bz_grid.store_dense_gp_map * 1 + 1, self._pp.bz_grid.D_diag, self._pp.bz_grid.Q, fc3, svecs, multi, masses, p2s, s2p, band_indices, self._temperatures, self._is_N_U * 1, symmetrize_fc3_q, self._pp.cutoff_frequency, ) else: if self._sigma_cutoff is None: sigma_cutoff = -1 else: sigma_cutoff = float(self._sigma_cutoff) phono3c.pp_collision_with_sigma( collisions, sigma, sigma_cutoff, self._frequencies, self._eigenvectors, triplets_at_q, weights_at_q, self._pp.bz_grid.addresses, self._pp.bz_grid.D_diag, self._pp.bz_grid.Q, fc3, svecs, multi, masses, p2s, s2p, band_indices, self._temperatures, self._is_N_U * 1, symmetrize_fc3_q, self._pp.cutoff_frequency, ) col_unit_conv = self._collision.unit_conversion_factor pp_unit_conv = self._pp.get_unit_conversion_factor() if self._is_N_U: col = collisions.sum(axis=0) col_N = collisions[0] col_U = collisions[1] else: col = collisions for k in range(len(self._temperatures)): self._gamma[j, k, i, :] = average_by_degeneracy( col[k] * col_unit_conv * pp_unit_conv, band_indices, self._frequencies[self._grid_points[i]], ) if self._is_N_U: self._gamma_N[j, k, i, :] = average_by_degeneracy( col_N[k] * col_unit_conv * pp_unit_conv, band_indices, self._frequencies[self._grid_points[i]], ) self._gamma_U[j, k, i, :] = average_by_degeneracy( col_U[k] * col_unit_conv * pp_unit_conv, band_indices, self._frequencies[self._grid_points[i]], )
class TetrahedronMesh: def __init__(self, cell, frequencies, # only at ir-grid-points mesh, grid_address, grid_mapping_table, ir_grid_points, grid_order=None): self._cell = cell self._frequencies = frequencies self._mesh = mesh self._grid_address = grid_address self._grid_mapping_table = grid_mapping_table if grid_order is None: self._grid_order = [1, mesh[0], mesh[0] * mesh[1]] else: self._grid_order = grid_order self._ir_grid_points = ir_grid_points self._gp_ir_index = None self._tm = None self._tetrahedra_frequencies = None self._integration_weights = None self._relative_grid_address = None self._frequency_points = None self._value = None self._grid_point_count = 0 self._prepare() def __iter__(self): return self def next(self): if self._grid_point_count == len(self._ir_grid_points): raise StopIteration else: gp = self._ir_grid_points[self._grid_point_count] self._set_tetrahedra_frequencies(gp) for ib, frequencies in enumerate(self._tetrahedra_frequencies): self._tm.set_tetrahedra_omegas(frequencies) self._tm.run(self._frequency_points, value=self._value) iw = self._tm.get_integration_weight() self._integration_weights[:, ib] = iw self._integration_weights /= np.prod(self._mesh) self._grid_point_count += 1 return self._integration_weights def get_integration_weights(self): return self._integration_weights def get_frequency_points(self): return self._frequency_points def set(self, value='I', division_number=201, frequency_points=None): self._grid_point_count = 0 self._value = value if frequency_points is None: max_frequency = np.amax(self._frequencies) min_frequency = np.amin(self._frequencies) self._frequency_points = np.linspace(min_frequency, max_frequency, division_number) else: self._frequency_points = frequency_points num_ir_grid_points = len(self._ir_grid_points) num_band = self._cell.get_number_of_atoms() * 3 num_freqs = len(self._frequency_points) self._integration_weights = np.zeros((num_freqs, num_band), dtype='double') reciprocal_lattice = np.linalg.inv(self._cell.get_cell()) self._tm = TetrahedronMethod(reciprocal_lattice, mesh=self._mesh) self._relative_grid_address = self._tm.get_tetrahedra() def _prepare(self): ir_gp_indices = {} for i, gp in enumerate(self._ir_grid_points): ir_gp_indices[gp] = i self._gp_ir_index = np.zeros_like(self._grid_mapping_table) for i, gp in enumerate(self._grid_mapping_table): self._gp_ir_index[i] = ir_gp_indices[gp] def _set_tetrahedra_frequencies(self, gp): self._tetrahedra_frequencies = get_tetrahedra_frequencies( gp, self._mesh, self._grid_order, self._grid_address, self._relative_grid_address, self._gp_ir_index, self._frequencies)
def _set_triplets_integration_weights_py(g, interaction, frequency_points): reciprocal_lattice = np.linalg.inv(interaction.get_primitive().get_cell()) mesh = interaction.get_mesh_numbers() thm = TetrahedronMethod(reciprocal_lattice, mesh=mesh) grid_address = interaction.get_grid_address() bz_map = interaction.get_bz_map() triplets_at_q = interaction.get_triplets_at_q()[0] unique_vertices = thm.get_unique_tetrahedra_vertices() tetrahedra_vertices = get_tetrahedra_vertices( thm.get_tetrahedra(), mesh, triplets_at_q, grid_address, bz_map) interaction.set_phonon(np.unique(tetrahedra_vertices)) frequencies = interaction.get_phonons()[0] num_band = frequencies.shape[1] for i, vertices in enumerate(tetrahedra_vertices): for j, k in list(np.ndindex((num_band, num_band))): f1_v = frequencies[vertices[0], j] f2_v = frequencies[vertices[1], k] thm.set_tetrahedra_omegas(f1_v + f2_v) thm.run(frequency_points) g0 = thm.get_integration_weight() g[0, i, :, j, k] = g0 thm.set_tetrahedra_omegas(-f1_v + f2_v) thm.run(frequency_points) g1 = thm.get_integration_weight() thm.set_tetrahedra_omegas(f1_v - f2_v) thm.run(frequency_points) g2 = thm.get_integration_weight() g[1, i, :, j, k] = g1 - g2 if len(g) == 3: g[2, i, :, j, k] = g0 + g1 + g2
def _run_py_tetrahedron_method(self): thm = TetrahedronMethod(self._reciprocal_lattice, mesh=self._mesh) self._vertices = get_tetrahedra_vertices( thm.get_tetrahedra(), self._mesh, self._triplets_at_q, self._grid_address, self._bz_map) self.set_phonon(self._vertices.ravel()) f_max = np.max(self._frequencies) * 2 f_max *= 1.005 f_min = 0 self._set_frequency_points(f_min, f_max) num_freq_points = len(self._frequency_points) jdos = np.zeros((num_freq_points, 2), dtype='double') for vertices, w in zip(self._vertices, self._weights_at_q): for i, j in list(np.ndindex(self._num_band, self._num_band)): f1 = self._frequencies[vertices[0], i] f2 = self._frequencies[vertices[1], j] thm.set_tetrahedra_omegas(f1 + f2) thm.run(self._frequency_points) iw = thm.get_integration_weight() jdos[:, 0] += iw * w thm.set_tetrahedra_omegas(f1 - f2) thm.run(self._frequency_points) iw = thm.get_integration_weight() jdos[:, 1] += iw * w thm.set_tetrahedra_omegas(-f1 + f2) thm.run(self._frequency_points) iw = thm.get_integration_weight() jdos[:, 1] += iw * w self._joint_dos = jdos / np.prod(self._mesh)
def _set_triplets_integration_weights_py(g, pp, frequency_points): """Python version of _set_triplets_integration_weights_c. Tetrahedron method engine is that implemented in phonopy written mainly in C. """ thm = TetrahedronMethod(pp.bz_grid.microzone_lattice) triplets_at_q = pp.get_triplets_at_q()[0] tetrahedra_vertices = _get_tetrahedra_vertices( np.array(np.dot(thm.get_tetrahedra(), pp.bz_grid.P.T), dtype="int_", order="C"), triplets_at_q, pp.bz_grid, ) pp.run_phonon_solver() frequencies = pp.get_phonons()[0] num_band = frequencies.shape[1] for i, vertices in enumerate(tetrahedra_vertices): for j, k in list(np.ndindex((num_band, num_band))): f1_v = frequencies[vertices[0], j] f2_v = frequencies[vertices[1], k] thm.set_tetrahedra_omegas(f1_v + f2_v) thm.run(frequency_points) g0 = thm.get_integration_weight() g[0, i, :, j, k] = g0 thm.set_tetrahedra_omegas(-f1_v + f2_v) thm.run(frequency_points) g1 = thm.get_integration_weight() thm.set_tetrahedra_omegas(f1_v - f2_v) thm.run(frequency_points) g2 = thm.get_integration_weight() g[1, i, :, j, k] = g1 - g2 if len(g) == 3: g[2, i, :, j, k] = g0 + g1 + g2