class Conductivity_RTA(Conductivity): def __init__(self, interaction, symmetry, grid_points=None, temperatures=np.arange(0, 1001, 10, dtype='double'), sigmas=[], is_isotope=False, mass_variances=None, boundary_mfp=None, # in micrometre use_averaged_pp_interaction=False, gamma_unit_conversion=None, mesh_divisors=None, coarse_mesh_shifts=None, no_kappa_stars=False, gv_delta_q=None, # finite difference for group veolocity log_level=0): self._pp = None self._temperatures = None self._sigmas = None self._no_kappa_stars = None self._gv_delta_q = None 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._gamma = None self._gamma_iso = None self._gamma_unit_conversion = gamma_unit_conversion self._use_ave_pp = use_averaged_pp_interaction 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, no_kappa_stars=no_kappa_stars, 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._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_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:", print len(self._pp.get_triplets_at_q()[0]) print "Calculating interaction..." self._collision.run_interaction() self._averaged_pp_interaction[i] = ( self._pp.get_averaged_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) self._cv[:, i, :] = self._get_cv(self._frequencies[grid_point]) self._set_gv(i) if self._log_level: self._show_log(self._qpoints[i], i) def _allocate_values(self): num_band = self._primitive.get_number_of_atoms() * 3 num_grid_points = len(self._grid_points) self._kappa = np.zeros((len(self._sigmas), len(self._temperatures), 6), dtype='double') self._mode_kappa = np.zeros((len(self._sigmas), len(self._temperatures), num_grid_points, num_band, 6), dtype='double') if not self._read_gamma: self._gamma = np.zeros((len(self._sigmas), len(self._temperatures), num_grid_points, num_band), dtype='double') self._gv = np.zeros((num_grid_points, num_band, 3), dtype='double') self._cv = np.zeros((len(self._temperatures), num_grid_points, num_band), dtype='double') if self._isotope is not None: self._gamma_iso = np.zeros((len(self._sigmas), num_grid_points, num_band), dtype='double') self._averaged_pp_interaction = np.zeros((num_grid_points, num_band), dtype='double') self._num_ignored_phonon_modes = np.zeros((len(self._sigmas), len(self._temperatures)), dtype='intc') self._collision = ImagSelfEnergy( self._pp, unit_conversion=self._gamma_unit_conversion) def _set_gamma_at_sigmas(self, i): for j, sigma in enumerate(self._sigmas): if self._log_level: print "Calculating Gamma of ph-ph with", if sigma is None: print "tetrahedron method" else: print "sigma=%s" % sigma self._collision.set_sigma(sigma) if not sigma: self._collision.set_integration_weights() 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() 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] gv = self._gv[i] ave_pp = self._averaged_pp_interaction[i] print "Frequency group velocity (x, y, z) |gv| Pqj", if self._gv_delta_q is None: print else: print " (dq=%3.1e)" % self._gv_delta_q 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))) 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) print else: 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)
class Conductivity_RTA(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, cutoff_mfp=None, # in micrometre no_kappa_stars=False, gv_delta_q=None, # finite difference for group veolocity log_level=0): self._pp = None self._temperatures = None self._sigmas = None self._no_kappa_stars = None self._gv_delta_q = None self._log_level = None self._primitive = None self._dm = None self._frequency_factor_to_THz = None self._cutoff_frequency = None self._cutoff_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._gamma = None self._read_gamma = False self._read_gamma_iso = False self._frequencies = None self._gv = None self._gamma_iso = None self._mean_square_pp_strength = 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, cutoff_mfp=cutoff_mfp, no_kappa_stars=no_kappa_stars, 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 num_sampling_points = 0 for i, grid_point in enumerate(self._grid_points): cv = self._cv[i] # 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) num_sampling_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 i == 0 and l < 3: # Exclude acoustic modes at Gamma continue self._mode_kappa[j, k, i, l] = (gv_sum2[:, l] * cv[k, l] / (g_sum[l] * 2) * self._conversion_factor) self._mode_kappa /= num_sampling_points self._kappa = self._mode_kappa.sum(axis=2).sum(axis=2) def get_mode_heat_capacities(self): return self._cv def _run_at_grid_point(self): i = self._grid_point_count self._show_log_header(i) grid_point = self._grid_points[i] if not self._read_gamma: self._collision.set_grid_point(grid_point) if self._log_level: print "Number of triplets:", print len(self._pp.get_triplets_at_q()[0]) print "Calculating interaction..." self._collision.run_interaction() self._set_gamma_at_sigmas(i) self._mean_square_pp_strength[i] = ( self._pp.get_mean_square_strength()) if self._isotope is not None and not self._read_gamma_iso: self._set_gamma_isotope_at_sigmas(i) self._cv[i] = self._get_cv(self._frequencies[grid_point]) self._set_gv(i) if self._log_level: self._show_log(self._qpoints[i], i) def _allocate_values(self): num_band = self._primitive.get_number_of_atoms() * 3 num_grid_points = len(self._grid_points) self._kappa = np.zeros((len(self._sigmas), len(self._temperatures), 6), dtype='double') self._mode_kappa = np.zeros((len(self._sigmas), len( self._temperatures), num_grid_points, num_band, 6), dtype='double') if not self._read_gamma: self._gamma = np.zeros((len(self._sigmas), len( self._temperatures), num_grid_points, num_band), dtype='double') self._gv = np.zeros((num_grid_points, num_band, 3), dtype='double') self._cv = np.zeros( (num_grid_points, len(self._temperatures), num_band), dtype='double') if self._isotope is not None: self._gamma_iso = np.zeros( (len(self._sigmas), num_grid_points, num_band), dtype='double') self._mean_square_pp_strength = np.zeros((num_grid_points, num_band), dtype='double') self._collision = ImagSelfEnergy(self._pp) def _set_gamma_at_sigmas(self, i): for j, sigma in enumerate(self._sigmas): if self._log_level: print "Calculating Gamma of ph-ph with", if sigma is None: print "tetrahedron method" else: print "sigma=%s" % sigma self._collision.set_sigma(sigma) if not sigma: self._collision.set_integration_weights() 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() 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] gv = self._gv[i] mspp = self._mean_square_pp_strength[i] print "Frequency group velocity (x, y, z) |gv| mspp", if self._gv_delta_q is None: print else: print " (dq=%3.1e)" % self._gv_delta_q 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))) for f, v, pp in zip(frequencies, np.dot(rot_c, gv.T).T, mspp): 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) print else: for f, v, pp in zip(frequencies, gv, mspp): 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)
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, 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._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._gamma = None self._gamma_iso = 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._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_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 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) self._kappa = np.zeros((len(self._sigmas), len(self._temperatures), 6), dtype='double') self._mode_kappa = np.zeros((len(self._sigmas), len( self._temperatures), num_grid_points, num_band0, 6), dtype='double') if not self._read_gamma: self._gamma = np.zeros((len(self._sigmas), len( self._temperatures), num_grid_points, num_band0), dtype='double') self._gv = np.zeros((num_grid_points, num_band0, 3), dtype='double') self._cv = np.zeros( (len(self._temperatures), 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), len(self._temperatures)), dtype='intc') self._collision = ImagSelfEnergy( self._pp, unit_conversion=self._gamma_unit_conversion) def _set_gamma_at_sigmas(self, i): for j, sigma in enumerate(self._sigmas): 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) self._collision.set_sigma(sigma) if not self._use_ave_pp: if sigma is None or self._run_with_g: self._collision.set_integration_weights() 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()) 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() 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)))
class Conductivity_RTA(Conductivity): def __init__(self, interaction, symmetry, grid_points=None, temperatures=np.arange(0, 1001, 10, dtype='double'), sigmas=[], mass_variances=None, mesh_divisors=None, coarse_mesh_shifts=None, cutoff_lifetime=1e-4, # in second no_kappa_stars=False, gv_delta_q=None, # finite difference for group veolocity log_level=0): self._pp = None self._temperatures = None self._sigmas = None self._no_kappa_stars = None self._gv_delta_q = None self._log_level = None self._primitive = None self._dm = None self._frequency_factor_to_THz = None self._cutoff_frequency = None self._cutoff_lifetime = 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._gamma = None self._read_gamma = False self._read_gamma_iso = False self._frequencies = None self._gv = None self._gamma_iso = None self._mesh = None self._mesh_divisors = None self._coarse_mesh = None self._coarse_mesh_shifts = None self._conversion_factor = None self._sum_num_kstar = 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, mass_variances=mass_variances, mesh_divisors=mesh_divisors, coarse_mesh_shifts=coarse_mesh_shifts, cutoff_lifetime=cutoff_lifetime, no_kappa_stars=no_kappa_stars, 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 num_sampling_points = 0 for i, grid_point in enumerate(self._grid_points): cv = self._cv[i] # 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) num_sampling_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, l in list(np.ndindex(len(self._temperatures), num_band)): g_phph = self._gamma[j, k, i, l] if g_phph < 0.5 / self._cutoff_lifetime / THz: continue if self._isotope is None: g_sum = g_phph else: g_iso = self._gamma_iso[j, i, l] g_sum = g_phph + g_iso self._kappa[j, k] += ( gv_sum2[:, l] * cv[k, l] / (g_sum * 2) * self._conversion_factor) self._kappa /= num_sampling_points def get_mode_heat_capacities(self): return self._cv def _run_at_grid_point(self): i = self._grid_point_count self._show_log_header(i) grid_point = self._grid_points[i] if not self._read_gamma: self._collision.set_grid_point(grid_point) if self._log_level: print "Number of triplets:", print len(self._pp.get_triplets_at_q()[0]) print "Calculating interaction..." self._collision.run_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) self._cv[i] = self._get_cv(self._frequencies[grid_point]) self._set_gv(i) if self._log_level: self._show_log(self._qpoints[i], i) def _allocate_values(self): num_band = self._primitive.get_number_of_atoms() * 3 num_grid_points = len(self._grid_points) self._kappa = np.zeros((len(self._sigmas), len(self._temperatures), 6), dtype='double') if not self._read_gamma: self._gamma = np.zeros((len(self._sigmas), len(self._temperatures), num_grid_points, num_band), dtype='double') self._gv = np.zeros((num_grid_points, num_band, 3), dtype='double') self._cv = np.zeros((num_grid_points, len(self._temperatures), num_band), dtype='double') if self._isotope is not None: self._gamma_iso = np.zeros((len(self._sigmas), num_grid_points, num_band), dtype='double') self._collision = ImagSelfEnergy(self._pp) def _set_gamma_at_sigmas(self, i): for j, sigma in enumerate(self._sigmas): if self._log_level: print "Calculating Gamma of ph-ph with", if sigma is None: print "tetrahedron method" else: print "sigma=%s" % sigma self._collision.set_sigma(sigma) if not sigma: self._collision.set_integration_weights() 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() def _get_gv_by_gv(self, i): rotation_map = get_grid_points_by_rotations( self._grid_points[i], self._point_operations, self._mesh) gv_by_gv = np.zeros((len(self._gv[i]), 3, 3), dtype='double') if self._no_kappa_stars: count = 0 for r, r_gp in zip(self._rotations_cartesian, rotation_map): if r_gp == rotation_map[0]: gvs_rot = np.dot(r, self._gv[i].T).T gv_by_gv += [np.outer(r_gv, r_gv) for r_gv in gvs_rot] count += 1 gv_by_gv /= count order_kstar = 1 else: for r in self._rotations_cartesian: gvs_rot = np.dot(r, self._gv[i].T).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)) # check if the number of rotations is correct. if self._grid_weights is not None: if len(set(rotation_map)) != 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 # assert len(rotations) == self._grid_weights[i], \ # "Num rotations %d, weight %d" % ( # len(rotations), self._grid_weights[i]) 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] gv = self._gv[i] print "Frequency group velocity (x, y, z) |gv|", if self._gv_delta_q is None: print else: print " (dq=%3.1e)" % self._gv_delta_q if self._log_level > 1: rotation_map = get_grid_points_by_rotations( 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))) 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: 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))