def __next__(self): if self._gp_index >= len(self._grid_points): if self._log_level: print("-" * 74) raise StopIteration if self._log_level: print(("-" * 24 + " Spectral function (%d/%d) " + "-" * 24) % (self._gp_index + 1, len(self._grid_points))) gp = self._grid_points[self._gp_index] ise = ImagSelfEnergy(self._interaction) ise.set_grid_point(gp) if self._log_level: print("Running ph-ph interaction calculation...") sys.stdout.flush() ise.run_interaction() for sigma_i, sigma in enumerate(self._sigmas): self._run_gamma(ise, self._gp_index, sigma, sigma_i) self._run_delta(self._gp_index, sigma_i) self._run_spectral_function(self._gp_index, gp, sigma_i) self._gp_index += 1 return gp
def __next__(self): """Calculate at next grid point.""" if self._gp_index >= len(self._grid_points): if self._log_level: print("-" * 74) raise StopIteration gp = self._grid_points[self._gp_index] qpoint = np.dot( self._pp.bz_grid.addresses[gp], self._pp.bz_grid.QDinv.T, ) if self._log_level: print(("-" * 24 + " Spectral function %d (%d/%d) " + "-" * 24) % (gp, self._gp_index + 1, len(self._grid_points))) print("q-point: (%5.2f %5.2f %5.2f)" % tuple(qpoint)) ise = ImagSelfEnergy(self._pp) ise.set_grid_point(gp) if self._log_level: print("Running ph-ph interaction calculation...") sys.stdout.flush() ise.run_interaction() for sigma_i, sigma in enumerate(self._sigmas): self._run_gamma(ise, self._gp_index, sigma, sigma_i) self._run_delta(self._gp_index, sigma_i) self._run_spectral_function(self._gp_index, gp, sigma_i) self._gp_index += 1 return gp
class Conductivity_RTA(Conductivity): def __init__( self, interaction, symmetry, grid_points=None, temperatures=None, sigmas=None, sigma_cutoff=None, is_isotope=False, mass_variances=None, boundary_mfp=None, # in micrometre use_ave_pp=False, gamma_unit_conversion=None, mesh_divisors=None, coarse_mesh_shifts=None, is_kappa_star=True, gv_delta_q=None, is_full_pp=False, read_pp=False, store_pp=False, pp_filename=None, is_N_U=False, is_gamma_detail=False, log_level=0): self._pp = None self._temperatures = None self._sigmas = None self._sigma_cutoff = None self._is_kappa_star = None self._gv_delta_q = None self._is_full_pp = None self._is_N_U = is_N_U self._is_gamma_detail = is_gamma_detail self._log_level = None self._primitive = None self._dm = None self._frequency_factor_to_THz = None self._cutoff_frequency = None self._boundary_mfp = None self._symmetry = None self._point_operations = None self._rotations_cartesian = None self._grid_points = None self._grid_weights = None self._grid_address = None self._read_gamma = False self._read_gamma_iso = False self._frequencies = None self._cv = None self._gv = None self._gv_sum2 = None self._gamma = None self._gamma_iso = None self._gamma_N = None self._gamma_U = None self._gamma_detail_at_q = None self._gamma_unit_conversion = gamma_unit_conversion self._use_ave_pp = use_ave_pp self._use_const_ave_pp = None self._averaged_pp_interaction = None self._num_ignored_phonon_modes = None self._num_sampling_grid_points = None self._mesh = None self._conversion_factor = None self._is_isotope = None self._isotope = None self._mass_variances = None self._grid_point_count = None Conductivity.__init__(self, interaction, symmetry, grid_points=grid_points, temperatures=temperatures, sigmas=sigmas, sigma_cutoff=sigma_cutoff, is_isotope=is_isotope, mass_variances=mass_variances, mesh_divisors=mesh_divisors, coarse_mesh_shifts=coarse_mesh_shifts, boundary_mfp=boundary_mfp, is_kappa_star=is_kappa_star, gv_delta_q=gv_delta_q, is_full_pp=is_full_pp, log_level=log_level) self._use_const_ave_pp = self._pp.get_constant_averaged_interaction() self._read_pp = read_pp self._store_pp = store_pp self._pp_filename = pp_filename if self._temperatures is not None: self._allocate_values() def set_kappa_at_sigmas(self): num_band = self._primitive.get_number_of_atoms() * 3 for i, grid_point in enumerate(self._grid_points): cv = self._cv[:, i, :] gp = self._grid_points[i] frequencies = self._frequencies[gp] # Kappa for j in range(len(self._sigmas)): for k in range(len(self._temperatures)): g_sum = self._get_main_diagonal(i, j, k) for l in range(num_band): if frequencies[l] < self._cutoff_frequency: self._num_ignored_phonon_modes[j, k] += 1 continue old_settings = np.seterr(all='raise') try: self._mode_kappa[j, k, i, l] = (self._gv_sum2[i, l] * cv[k, l] / (g_sum[l] * 2) * self._conversion_factor) except FloatingPointError: # supposed that g is almost 0 and |gv|=0 pass except: print("=" * 26 + " Warning " + "=" * 26) print(" Unexpected physical condition of ph-ph " "interaction calculation was found.") print(" g=%f at gp=%d, band=%d, freq=%f" % (g_sum[l], gp, l + 1, frequencies[l])) print("=" * 61) np.seterr(**old_settings) N = self._num_sampling_grid_points self._kappa = self._mode_kappa.sum(axis=2).sum(axis=2) / N def get_gamma_N_U(self): return (self._gamma_N, self._gamma_U) def set_gamma_N_U(self, gamma_N, gamma_U): self._gamma_N = gamma_N self._gamma_U = gamma_U def get_gamma_detail_at_q(self): return self._gamma_detail_at_q def get_number_of_ignored_phonon_modes(self): return self._num_ignored_phonon_modes def get_number_of_sampling_grid_points(self): return self._num_sampling_grid_points def set_averaged_pp_interaction(self, ave_pp): self._averaged_pp_interaction = ave_pp def _run_at_grid_point(self): i = self._grid_point_count self._show_log_header(i) grid_point = self._grid_points[i] self._set_harmonic_properties(i, i) if self._read_gamma: if self._use_ave_pp: self._collision.set_grid_point(grid_point) self._set_gamma_at_sigmas(i) else: self._collision.set_grid_point( grid_point, stores_triplets_map=(self._is_full_pp or self._is_gamma_detail)) num_triplets = len(self._pp.get_triplets_at_q()[0]) if self._log_level: print("Number of triplets: %d" % num_triplets) if (self._is_full_pp or self._read_pp or self._store_pp or self._use_ave_pp or self._use_const_ave_pp or self._is_gamma_detail): self._set_gamma_at_sigmas(i) else: # can save memory space self._set_gamma_at_sigmas_lowmem(i) if self._isotope is not None and not self._read_gamma_iso: gamma_iso = self._get_gamma_isotope_at_sigmas(i) self._gamma_iso[:, i, :] = gamma_iso[:, self._pp.get_band_indices()] if self._log_level: self._show_log(self._qpoints[i], i) def _allocate_values(self): num_band0 = len(self._pp.get_band_indices()) num_grid_points = len(self._grid_points) num_temp = len(self._temperatures) self._kappa = np.zeros((len(self._sigmas), num_temp, 6), order='C', dtype='double') self._mode_kappa = np.zeros( (len(self._sigmas), num_temp, num_grid_points, num_band0, 6), order='C', dtype='double') if not self._read_gamma: self._gamma = np.zeros( (len(self._sigmas), num_temp, num_grid_points, num_band0), order='C', dtype='double') if self._is_gamma_detail or self._is_N_U: self._gamma_N = np.zeros_like(self._gamma) self._gamma_U = np.zeros_like(self._gamma) self._gv = np.zeros((num_grid_points, num_band0, 3), order='C', dtype='double') self._gv_sum2 = np.zeros((num_grid_points, num_band0, 6), order='C', dtype='double') self._cv = np.zeros((num_temp, num_grid_points, num_band0), order='C', dtype='double') if self._isotope is not None: self._gamma_iso = np.zeros( (len(self._sigmas), num_grid_points, num_band0), order='C', dtype='double') if self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp: self._averaged_pp_interaction = np.zeros( (num_grid_points, num_band0), order='C', dtype='double') self._num_ignored_phonon_modes = np.zeros( (len(self._sigmas), num_temp), order='C', dtype='intc') self._collision = ImagSelfEnergy( self._pp, with_detail=(self._is_gamma_detail or self._is_N_U), unit_conversion=self._gamma_unit_conversion) def _set_gamma_at_sigmas(self, i): for j, sigma in enumerate(self._sigmas): self._collision.set_sigma(sigma, sigma_cutoff=self._sigma_cutoff) self._collision.set_integration_weights() if self._log_level: text = "Collisions will be calculated with " if sigma is None: text += "tetrahedron method." else: text += "sigma=%s" % sigma if self._sigma_cutoff is None: text += "." else: text += "(%4.2f SD)." % self._sigma_cutoff print(text) if self._read_pp: pp, _g_zero = read_pp_from_hdf5( self._mesh, grid_point=self._grid_points[i], sigma=sigma, sigma_cutoff=self._sigma_cutoff, filename=self._pp_filename, verbose=(self._log_level > 0)) _, g_zero = self._collision.get_integration_weights() if self._log_level: if len(self._sigmas) > 1: print("Multiple sigmas or mixing smearing and " "tetrahedron method is not supported.") if _g_zero is not None and (_g_zero != g_zero).any(): raise ValueError("Inconsistency found in g_zero.") self._collision.set_interaction_strength(pp) elif self._use_ave_pp: self._collision.set_averaged_pp_interaction( self._averaged_pp_interaction[i]) elif self._use_const_ave_pp: if self._log_level: print("Constant ph-ph interaction of %6.3e is used." % self._pp.get_constant_averaged_interaction()) self._collision.run_interaction() self._averaged_pp_interaction[i] = ( self._pp.get_averaged_interaction()) elif j != 0 and (self._is_full_pp or self._sigma_cutoff is None): if self._log_level: print("Existing ph-ph interaction is used.") else: if self._log_level: print("Calculating ph-ph interaction...") self._collision.run_interaction(is_full_pp=self._is_full_pp) if self._is_full_pp: self._averaged_pp_interaction[i] = ( self._pp.get_averaged_interaction()) # Number of triplets depends on q-point. # So this is allocated each time. if self._is_gamma_detail: num_temp = len(self._temperatures) self._gamma_detail_at_q = np.empty( ((num_temp, ) + self._pp.get_interaction_strength().shape), dtype='double', order='C') self._gamma_detail_at_q[:] = 0 if self._log_level: print("Calculating collisions at temperatures...") for k, t in enumerate(self._temperatures): self._collision.set_temperature(t) self._collision.run() self._gamma[j, k, i] = self._collision.get_imag_self_energy() if self._is_N_U or self._is_gamma_detail: g_N, g_U = self._collision.get_imag_self_energy_N_and_U() self._gamma_N[j, k, i] = g_N self._gamma_U[j, k, i] = g_U if self._is_gamma_detail: self._gamma_detail_at_q[k] = ( self._collision.get_detailed_imag_self_energy()) 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 if None in self._sigmas: reclat = np.linalg.inv(self._pp.get_primitive().get_cell()) thm = TetrahedronMethod(reclat, 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 if sigma is None: 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) 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._grid_address, 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 _show_log(self, q, i): gp = self._grid_points[i] frequencies = self._frequencies[gp][self._pp.get_band_indices()] gv = self._gv[i] if self._averaged_pp_interaction is not None: ave_pp = self._averaged_pp_interaction[i] else: ave_pp = None self._show_log_value_names() if self._log_level > 1: self._show_log_values_on_kstar(frequencies, gv, ave_pp, gp, q) else: self._show_log_values(frequencies, gv, ave_pp) sys.stdout.flush() def _show_log_values(self, frequencies, gv, ave_pp): if self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp: for f, v, pp in zip(frequencies, gv, ave_pp): print("%8.3f (%8.3f %8.3f %8.3f) %8.3f %11.3e" % (f, v[0], v[1], v[2], np.linalg.norm(v), pp)) else: for f, v in zip(frequencies, gv): print("%8.3f (%8.3f %8.3f %8.3f) %8.3f" % (f, v[0], v[1], v[2], np.linalg.norm(v))) def _show_log_values_on_kstar(self, frequencies, gv, ave_pp, gp, q): rotation_map = get_grid_points_by_rotations(self._grid_address[gp], self._point_operations, self._mesh) for i, j in enumerate(np.unique(rotation_map)): for k, (rot, rot_c) in enumerate( zip(self._point_operations, self._rotations_cartesian)): if rotation_map[k] != j: continue print(" k*%-2d (%5.2f %5.2f %5.2f)" % ((i + 1, ) + tuple(np.dot(rot, q)))) if (self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp): for f, v, pp in zip(frequencies, np.dot(rot_c, gv.T).T, ave_pp): print("%8.3f (%8.3f %8.3f %8.3f) %8.3f %11.3e" % (f, v[0], v[1], v[2], np.linalg.norm(v), pp)) else: for f, v in zip(frequencies, np.dot(rot_c, gv.T).T): print("%8.3f (%8.3f %8.3f %8.3f) %8.3f" % (f, v[0], v[1], v[2], np.linalg.norm(v))) print('') def _show_log_value_names(self): if self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp: text = "Frequency group velocity (x, y, z) |gv| Pqj" else: text = "Frequency group velocity (x, y, z) |gv|" if self._gv_delta_q is None: pass else: text += " (dq=%3.1e)" % self._gv_delta_q print(text)
class ConductivityRTABase(ConductivityBase): """Base class of ConductivityRTA*. This is a base class of RTA classes. """ def __init__( self, interaction: Interaction, grid_points=None, temperatures=None, sigmas=None, sigma_cutoff=None, is_isotope=False, mass_variances=None, boundary_mfp=None, # in micrometre use_ave_pp=False, is_kappa_star=True, gv_delta_q=None, is_full_pp=False, read_pp=False, store_pp=False, pp_filename=None, is_N_U=False, is_gamma_detail=False, is_frequency_shift_by_bubble=False, log_level=0, ): """Init method.""" self._is_N_U = is_N_U self._is_gamma_detail = is_gamma_detail self._is_frequency_shift_by_bubble = is_frequency_shift_by_bubble self._gamma_N = None self._gamma_U = None self._gamma_detail_at_q = None self._use_ave_pp = use_ave_pp self._use_const_ave_pp = None self._averaged_pp_interaction = None self._num_ignored_phonon_modes = None super().__init__( interaction, grid_points=grid_points, temperatures=temperatures, sigmas=sigmas, sigma_cutoff=sigma_cutoff, is_isotope=is_isotope, mass_variances=mass_variances, boundary_mfp=boundary_mfp, is_kappa_star=is_kappa_star, gv_delta_q=gv_delta_q, is_full_pp=is_full_pp, log_level=log_level, ) self._use_const_ave_pp = self._pp.get_constant_averaged_interaction() self._read_pp = read_pp self._store_pp = store_pp self._pp_filename = pp_filename if self._temperatures is not None: self._allocate_values() self._collision = ImagSelfEnergy( self._pp, with_detail=(self._is_gamma_detail or self._is_N_U) ) def get_gamma_N_U(self): """Return N and U parts of gamma.""" return (self._gamma_N, self._gamma_U) def set_gamma_N_U(self, gamma_N, gamma_U): """Set N and U parts of gamma.""" self._gamma_N = gamma_N self._gamma_U = gamma_U def get_gamma_detail_at_q(self): """Return contribution of each triplet to gamma at current q-point.""" return self._gamma_detail_at_q def get_number_of_ignored_phonon_modes(self): """Return number of ignored phonon modes.""" return self._num_ignored_phonon_modes def set_averaged_pp_interaction(self, ave_pp): """Set averaged ph-ph interaction.""" self._averaged_pp_interaction = ave_pp @abstractmethod def set_kappa_at_sigmas(self): """Must be implementated in the inherited class.""" raise NotImplementedError() def _allocate_values(self): num_band0 = len(self._pp.band_indices) num_grid_points = len(self._grid_points) num_temp = len(self._temperatures) if not self._read_gamma: self._gamma = np.zeros( (len(self._sigmas), num_temp, num_grid_points, num_band0), order="C", dtype="double", ) if self._is_gamma_detail or self._is_N_U: self._gamma_N = np.zeros_like(self._gamma) self._gamma_U = np.zeros_like(self._gamma) self._gv = np.zeros((num_grid_points, num_band0, 3), order="C", dtype="double") if self._is_isotope: self._gamma_iso = np.zeros( (len(self._sigmas), num_grid_points, num_band0), order="C", dtype="double", ) if self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp: self._averaged_pp_interaction = np.zeros( (num_grid_points, num_band0), order="C", dtype="double" ) self._num_ignored_phonon_modes = np.zeros( (len(self._sigmas), num_temp), order="C", dtype="intc" ) def _run_at_grid_point(self): i_gp = self._grid_point_count self._show_log_header(i_gp) grid_point = self._grid_points[i_gp] self._set_cv(i_gp, i_gp) self._set_velocities(i_gp, i_gp) if self._read_gamma: if self._use_ave_pp: self._collision.set_grid_point(grid_point) self._set_gamma_at_sigmas(i_gp) else: self._collision.set_grid_point(grid_point) num_triplets = len(self._pp.get_triplets_at_q()[0]) if self._log_level: print("Number of triplets: %d" % num_triplets) if ( self._is_full_pp or self._read_pp or self._store_pp or self._use_ave_pp or self._use_const_ave_pp or self._is_gamma_detail ): self._set_gamma_at_sigmas(i_gp) else: # can save memory space self._set_gamma_at_sigmas_lowmem(i_gp) if self._is_isotope and not self._read_gamma_iso: gamma_iso = self._get_gamma_isotope_at_sigmas(i_gp) self._gamma_iso[:, i_gp, :] = gamma_iso[:, self._pp.band_indices] if self._log_level: self._show_log(i_gp) def _set_gamma_at_sigmas(self, i): for j, sigma in enumerate(self._sigmas): self._collision.set_sigma(sigma, sigma_cutoff=self._sigma_cutoff) self._collision.run_integration_weights() if self._log_level: text = "Collisions will be calculated with " if sigma is None: text += "tetrahedron method." else: text += "sigma=%s" % sigma if self._sigma_cutoff is None: text += "." else: text += "(%4.2f SD)." % self._sigma_cutoff print(text) if self._read_pp: pp, _g_zero = read_pp_from_hdf5( self._pp.mesh_numbers, grid_point=self._grid_points[i], sigma=sigma, sigma_cutoff=self._sigma_cutoff, filename=self._pp_filename, verbose=(self._log_level > 0), ) _, g_zero = self._collision.get_integration_weights() if self._log_level: if len(self._sigmas) > 1: print( "Multiple sigmas or mixing smearing and " "tetrahedron method is not supported." ) if _g_zero is not None and (_g_zero != g_zero).any(): raise ValueError("Inconsistency found in g_zero.") self._collision.set_interaction_strength(pp) elif self._use_ave_pp: self._collision.set_averaged_pp_interaction( self._averaged_pp_interaction[i] ) elif self._use_const_ave_pp: if self._log_level: print( "Constant ph-ph interaction of %6.3e is used." % self._pp.get_constant_averaged_interaction() ) self._collision.run_interaction() self._averaged_pp_interaction[i] = self._pp.get_averaged_interaction() elif j != 0 and (self._is_full_pp or self._sigma_cutoff is None): if self._log_level: print("Existing ph-ph interaction is used.") else: if self._log_level: print("Calculating ph-ph interaction...") self._collision.run_interaction(is_full_pp=self._is_full_pp) if self._is_full_pp: self._averaged_pp_interaction[ i ] = self._pp.get_averaged_interaction() # Number of triplets depends on q-point. # So this is allocated each time. if self._is_gamma_detail: num_temp = len(self._temperatures) self._gamma_detail_at_q = np.empty( ((num_temp,) + self._pp.get_interaction_strength().shape), dtype="double", order="C", ) self._gamma_detail_at_q[:] = 0 if self._log_level: print("Calculating collisions at temperatures...") for k, t in enumerate(self._temperatures): self._collision.temperature = t self._collision.run() self._gamma[j, k, i] = self._collision.imag_self_energy if self._is_N_U or self._is_gamma_detail: g_N, g_U = self._collision.get_imag_self_energy_N_and_U() self._gamma_N[j, k, i] = g_N self._gamma_U[j, k, i] = g_U if self._is_gamma_detail: self._gamma_detail_at_q[ k ] = self._collision.get_detailed_imag_self_energy() 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]], ) def _show_log(self, i_gp): q = self._get_qpoint_from_gp_index(i_gp) gp = self._grid_points[i_gp] frequencies = self._frequencies[gp][self._pp.band_indices] gv = self._gv[i_gp] if self._averaged_pp_interaction is not None: ave_pp = self._averaged_pp_interaction[i_gp] else: ave_pp = None self._show_log_value_names() if self._log_level > 2: self._show_log_values_on_kstar(frequencies, gv, ave_pp, gp, q) else: self._show_log_values(frequencies, gv, ave_pp) print("", end="", flush=True) def _show_log_values(self, frequencies, gv, ave_pp): if self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp: for f, v, pp in zip(frequencies, gv, ave_pp): print( "%8.3f (%8.3f %8.3f %8.3f) %8.3f %11.3e" % (f, v[0], v[1], v[2], np.linalg.norm(v), pp) ) else: for f, v in zip(frequencies, gv): print( "%8.3f (%8.3f %8.3f %8.3f) %8.3f" % (f, v[0], v[1], v[2], np.linalg.norm(v)) ) def _show_log_values_on_kstar(self, frequencies, gv, ave_pp, gp, q): rotation_map = get_grid_points_by_rotations(gp, self._pp.bz_grid) for i, j in enumerate(np.unique(rotation_map)): for k, (rot, rot_c) in enumerate( zip(self._point_operations, self._rotations_cartesian) ): if rotation_map[k] != j: continue print( " k*%-2d (%5.2f %5.2f %5.2f)" % ((i + 1,) + tuple(np.dot(rot, q))) ) if self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp: for f, v, pp in zip(frequencies, np.dot(rot_c, gv.T).T, ave_pp): print( "%8.3f (%8.3f %8.3f %8.3f) %8.3f %11.3e" % (f, v[0], v[1], v[2], np.linalg.norm(v), pp) ) else: for f, v in zip(frequencies, np.dot(rot_c, gv.T).T): print( "%8.3f (%8.3f %8.3f %8.3f) %8.3f" % (f, v[0], v[1], v[2], np.linalg.norm(v)) ) print("") def _show_log_value_names(self): if self._is_full_pp or self._use_ave_pp or self._use_const_ave_pp: text = "Frequency group velocity (x, y, z) |gv| Pqj" else: text = "Frequency group velocity (x, y, z) |gv|" if self._velocity_obj.q_length is None: pass else: text += " (dq=%3.1e)" % self._velocity_obj.q_length print(text)
class Conductivity_RTA(Conductivity): def __init__( self, interaction, symmetry, grid_points=None, temperatures=np.arange(0, 1001, 10, dtype='double'), sigmas=None, is_isotope=False, mass_variances=None, boundary_mfp=None, # in micrometre use_ave_pp=False, gamma_unit_conversion=None, mesh_divisors=None, coarse_mesh_shifts=None, is_kappa_star=True, gv_delta_q=None, run_with_g=True, is_full_pp=False, is_gamma_detail=False, log_level=0): self._pp = None self._temperatures = None self._sigmas = None self._is_kappa_star = None self._gv_delta_q = None self._run_with_g = run_with_g self._is_full_pp = is_full_pp self._is_gamma_detail = is_gamma_detail self._log_level = None self._primitive = None self._dm = None self._frequency_factor_to_THz = None self._cutoff_frequency = None self._boundary_mfp = None self._symmetry = None self._point_operations = None self._rotations_cartesian = None self._grid_points = None self._grid_weights = None self._grid_address = None self._read_gamma = False self._read_gamma_iso = False self._frequencies = None self._gv = None self._gv_sum2 = None self._gamma = None self._gamma_iso = None self._gamma_N = None self._gamma_U = None self._gamma_detail_at_q = None self._gamma_unit_conversion = gamma_unit_conversion self._use_ave_pp = use_ave_pp self._averaged_pp_interaction = None self._num_ignored_phonon_modes = None self._num_sampling_grid_points = None self._mesh = None self._mesh_divisors = None self._coarse_mesh = None self._coarse_mesh_shifts = None self._conversion_factor = None self._is_isotope = None self._isotope = None self._mass_variances = None self._grid_point_count = None Conductivity.__init__(self, interaction, symmetry, grid_points=grid_points, temperatures=temperatures, sigmas=sigmas, is_isotope=is_isotope, mass_variances=mass_variances, mesh_divisors=mesh_divisors, coarse_mesh_shifts=coarse_mesh_shifts, boundary_mfp=boundary_mfp, is_kappa_star=is_kappa_star, gv_delta_q=gv_delta_q, log_level=log_level) self._cv = None if self._temperatures is not None: self._allocate_values() def set_kappa_at_sigmas(self): num_band = self._primitive.get_number_of_atoms() * 3 self._num_sampling_grid_points = 0 for i, grid_point in enumerate(self._grid_points): cv = self._cv[:, i, :] gp = self._grid_points[i] frequencies = self._frequencies[gp] # Outer product of group velocities (v x v) [num_k*, num_freqs, 3, 3] gv_by_gv_tensor, order_kstar = self._get_gv_by_gv(i) self._num_sampling_grid_points += order_kstar # Sum all vxv at k* gv_sum2 = np.zeros((6, num_band), dtype='double') for j, vxv in enumerate( ([0, 0], [1, 1], [2, 2], [1, 2], [0, 2], [0, 1])): gv_sum2[j] = gv_by_gv_tensor[:, vxv[0], vxv[1]] # Kappa for j in range(len(self._sigmas)): for k in range(len(self._temperatures)): g_sum = self._get_main_diagonal(i, j, k) for l in range(num_band): if frequencies[l] < self._cutoff_frequency: self._num_ignored_phonon_modes[j, k] += 1 continue self._mode_kappa[j, k, i, l] = (gv_sum2[:, l] * cv[k, l] / (g_sum[l] * 2) * self._conversion_factor) self._gv_sum2[i] = gv_sum2.T self._mode_kappa /= self._num_sampling_grid_points self._kappa = self._mode_kappa.sum(axis=2).sum(axis=2) def get_mode_heat_capacities(self): return self._cv def get_gv_by_gv(self): return self._gv_sum2 def get_gamma_N_U(self): return (self._gamma_N, self._gamma_U) def get_gamma_detail_at_q(self): return self._gamma_detail_at_q def get_number_of_ignored_phonon_modes(self): return self._num_ignored_phonon_modes def get_number_of_sampling_grid_points(self): return self._num_sampling_grid_points def get_averaged_pp_interaction(self): return self._averaged_pp_interaction def set_averaged_pp_interaction(self, ave_pp): self._averaged_pp_interaction = ave_pp def _run_at_grid_point(self): i = self._grid_point_count self._show_log_header(i) grid_point = self._grid_points[i] if self._read_gamma: if self._use_ave_pp: self._collision.set_grid_point(grid_point) self._collision.set_averaged_pp_interaction( self._averaged_pp_interaction[i]) self._set_gamma_at_sigmas(i) else: self._collision.set_grid_point(grid_point) if self._log_level: print("Number of triplets: %d" % len(self._pp.get_triplets_at_q()[0])) print("Calculating ph-ph interaction...") self._set_gamma_at_sigmas(i) if self._isotope is not None and not self._read_gamma_iso: self._set_gamma_isotope_at_sigmas(i) freqs = self._frequencies[grid_point][self._pp.get_band_indices()] self._cv[:, i, :] = self._get_cv(freqs) self._set_gv(i) if self._log_level: self._show_log(self._qpoints[i], i) def _allocate_values(self): num_band0 = len(self._pp.get_band_indices()) num_band = self._primitive.get_number_of_atoms() * 3 num_grid_points = len(self._grid_points) num_temp = len(self._temperatures) self._kappa = np.zeros((len(self._sigmas), num_temp, 6), dtype='double') self._mode_kappa = np.zeros( (len(self._sigmas), num_temp, num_grid_points, num_band0, 6), dtype='double') if not self._read_gamma: self._gamma = np.zeros( (len(self._sigmas), num_temp, num_grid_points, num_band0), dtype='double') if self._is_gamma_detail: self._gamma_N = np.zeros_like(self._gamma) self._gamma_U = np.zeros_like(self._gamma) self._gv = np.zeros((num_grid_points, num_band0, 3), dtype='double') self._gv_sum2 = np.zeros((num_grid_points, num_band0, 6), dtype='double') self._cv = np.zeros((num_temp, num_grid_points, num_band0), dtype='double') if self._isotope is not None: self._gamma_iso = np.zeros( (len(self._sigmas), num_grid_points, num_band0), dtype='double') if self._is_full_pp or self._use_ave_pp: self._averaged_pp_interaction = np.zeros( (num_grid_points, num_band0), dtype='double') self._num_ignored_phonon_modes = np.zeros( (len(self._sigmas), num_temp), dtype='intc') self._collision = ImagSelfEnergy( self._pp, with_detail=self._is_gamma_detail, unit_conversion=self._gamma_unit_conversion) def _set_gamma_at_sigmas(self, i): for j, sigma in enumerate(self._sigmas): self._collision.set_sigma(sigma) if sigma is None or self._run_with_g: self._collision.set_integration_weights() if not self._use_ave_pp: if self._log_level: text = "Calculating Gamma of ph-ph with " if sigma is None: text += "tetrahedron method" else: text += "sigma=%s" % sigma print(text) if self._is_full_pp and j != 0: pass else: self._collision.run_interaction( is_full_pp=self._is_full_pp) if self._is_full_pp and j == 0: self._averaged_pp_interaction[i] = ( self._pp.get_averaged_interaction()) # Number of triplets depends on q-point. # So this is allocated each time. if self._is_gamma_detail: num_temp = len(self._temperatures) self._gamma_detail_at_q = np.zeros( ((num_temp, ) + self._pp.get_interaction_strength().shape), dtype='double', order='C') for k, t in enumerate(self._temperatures): self._collision.set_temperature(t) self._collision.run() self._gamma[j, k, i] = self._collision.get_imag_self_energy() if self._is_gamma_detail: g_N, g_U = self._collision.get_imag_self_energy_N_and_U() self._gamma_N[j, k, i] = g_N self._gamma_U[j, k, i] = g_U self._gamma_detail_at_q[k] = ( self._collision.get_detailed_imag_self_energy()) def _get_gv_by_gv(self, i): rotation_map = get_grid_points_by_rotations( self._grid_address[self._grid_points[i]], self._point_operations, self._mesh) gv_by_gv = np.zeros((len(self._gv[i]), 3, 3), dtype='double') for r in self._rotations_cartesian: gvs_rot = np.dot(self._gv[i], r.T) gv_by_gv += [np.outer(r_gv, r_gv) for r_gv in gvs_rot] gv_by_gv /= len(rotation_map) // len(np.unique(rotation_map)) order_kstar = len(np.unique(rotation_map)) if order_kstar != self._grid_weights[i]: if self._log_level: print("*" * 33 + "Warning" + "*" * 33) print(" Number of elements in k* is unequal " "to number of equivalent grid-points.") print("*" * 73) return gv_by_gv, order_kstar 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 _show_log(self, q, i): gp = self._grid_points[i] frequencies = self._frequencies[gp][self._pp.get_band_indices()] gv = self._gv[i] if self._is_full_pp or self._use_ave_pp: ave_pp = self._averaged_pp_interaction[i] if self._is_full_pp or self._use_ave_pp: text = "Frequency group velocity (x, y, z) |gv| Pqj" else: text = "Frequency group velocity (x, y, z) |gv|" if self._gv_delta_q is None: pass else: text += " (dq=%3.1e)" % self._gv_delta_q print(text) if self._log_level > 1: rotation_map = get_grid_points_by_rotations( self._grid_address[gp], self._point_operations, self._mesh) for i, j in enumerate(np.unique(rotation_map)): for k, (rot, rot_c) in enumerate( zip(self._point_operations, self._rotations_cartesian)): if rotation_map[k] != j: continue print(" k*%-2d (%5.2f %5.2f %5.2f)" % ((i + 1, ) + tuple(np.dot(rot, q)))) if self._is_full_pp or self._use_ave_pp: for f, v, pp in zip(frequencies, np.dot(rot_c, gv.T).T, ave_pp): print("%8.3f (%8.3f %8.3f %8.3f) %8.3f %11.3e" % (f, v[0], v[1], v[2], np.linalg.norm(v), pp)) else: for f, v in zip(frequencies, np.dot(rot_c, gv.T).T): print("%8.3f (%8.3f %8.3f %8.3f) %8.3f" % (f, v[0], v[1], v[2], np.linalg.norm(v))) print('') else: if self._is_full_pp or self._use_ave_pp: for f, v, pp in zip(frequencies, gv, ave_pp): print("%8.3f (%8.3f %8.3f %8.3f) %8.3f %11.3e" % (f, v[0], v[1], v[2], np.linalg.norm(v), pp)) else: for f, v in zip(frequencies, gv): print("%8.3f (%8.3f %8.3f %8.3f) %8.3f" % (f, v[0], v[1], v[2], np.linalg.norm(v)))