Esempio n. 1
0
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)
Esempio n. 2
0
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)
Esempio n. 3
0
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)))
Esempio n. 4
0
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))