Пример #1
0
 def __init__(self, **kwargs):
     self.forceconstants = kwargs.pop('forceconstants')
     self.is_classic = bool(kwargs.pop('is_classic', False))
     if 'temperature' in kwargs:
         self.temperature = float(kwargs['temperature'])
     self.folder = kwargs.pop('folder', FOLDER_NAME)
     self.kpts = kwargs.pop('kpts', (1, 1, 1))
     self._grid_type = kwargs.pop('grid_type', 'C')
     self._reciprocal_grid = Grid(self.kpts, order=self._grid_type)
     self.is_unfolding = kwargs.pop('is_unfolding', False)
     if self.is_unfolding:
         logging.info('Using unfolding.')
     self.kpts = np.array(self.kpts)
     self.min_frequency = kwargs.pop('min_frequency', 0)
     self.max_frequency = kwargs.pop('max_frequency', None)
     self.broadening_shape = kwargs.pop('broadening_shape', 'gauss')
     self.is_nw = kwargs.pop('is_nw', False)
     self.third_bandwidth = kwargs.pop('third_bandwidth', None)
     self.storage = kwargs.pop('storage', 'formatted')
     self.is_symmetrizing_frequency = kwargs.pop(
         'is_symmetrizing_frequency', False)
     self.is_antisymmetrizing_velocity = kwargs.pop(
         'is_antisymmetrizing_velocity', False)
     self.is_balanced = kwargs.pop('is_balanced', False)
     self.atoms = self.forceconstants.atoms
     self.supercell = np.array(self.forceconstants.supercell)
     self.n_k_points = int(np.prod(self.kpts))
     self.n_atoms = self.forceconstants.n_atoms
     self.n_modes = self.forceconstants.n_modes
     self.n_phonons = self.n_k_points * self.n_modes
     self.is_able_to_calculate = True
     self.hbar = units._hbar
     if self.is_classic:
         self.hbar = self.hbar * 1e-6
Пример #2
0
 def from_supercell(cls, atoms, supercell, grid_type, value=None, folder='kALDo'):
     _direct_grid = Grid(supercell, grid_type)
     replicated_positions = _direct_grid.grid(is_wrapping=False).dot(atoms.cell)[:, np.newaxis, :] + atoms.positions[
                                                                                    np.newaxis, :, :]
     inst = cls(atoms=atoms,
                replicated_positions=replicated_positions,
                supercell=supercell,
                value=value,
                folder=folder)
     inst._direct_grid = _direct_grid
     return inst
Пример #3
0
def read_third_order_matrix(third_file, atoms, supercell, order='C'):
    n_unit_atoms = atoms.positions.shape[0]
    n_replicas = np.prod(supercell)
    third_order = np.zeros((n_unit_atoms, 3, n_replicas, n_unit_atoms, 3,
                            n_replicas, n_unit_atoms, 3))
    second_cell_list = []
    third_cell_list = []

    current_grid = Grid(supercell, order=order).grid(is_wrapping=True)
    list_of_index = current_grid
    list_of_replicas = list_of_index.dot(atoms.cell)
    with open(third_file, 'r') as file:
        line = file.readline()
        n_third = int(line)
        for i in range(n_third):
            file.readline()
            file.readline()
            second_cell_position = np.fromstring(file.readline(),
                                                 dtype=np.float,
                                                 sep=' ')
            second_cell_index = second_cell_position.dot(
                np.linalg.inv(atoms.cell)).round(0).astype(int)
            second_cell_list.append(second_cell_index)

            # create mask to find the index
            second_cell_id = (list_of_index[:] == second_cell_index).prod(
                axis=1)
            second_cell_id = np.argwhere(second_cell_id).flatten()

            third_cell_position = np.fromstring(file.readline(),
                                                dtype=np.float,
                                                sep=' ')
            third_cell_index = third_cell_position.dot(
                np.linalg.inv(atoms.cell)).round(0).astype(int)
            third_cell_list.append(third_cell_index)

            # create mask to find the index
            third_cell_id = (list_of_index[:] == third_cell_index).prod(axis=1)
            third_cell_id = np.argwhere(third_cell_id).flatten()

            atom_i, atom_j, atom_k = np.fromstring(
                file.readline(), dtype=np.int, sep=' ') - 1
            for _ in range(27):
                values = np.fromstring(file.readline(),
                                       dtype=np.float,
                                       sep=' ')
                alpha, beta, gamma = values[:3].round(0).astype(int) - 1
                third_order[atom_i, alpha, second_cell_id, atom_j, beta,
                            third_cell_id, atom_k, gamma] = values[3]

    third_order = third_order.reshape(
        (n_unit_atoms * 3, n_replicas * n_unit_atoms * 3,
         n_replicas * n_unit_atoms * 3))
    return third_order
Пример #4
0
    def __init__(self, *kargs, **kwargs):
        Observable.__init__(self, *kargs, **kwargs)
        self.atoms = kwargs['atoms']
        replicated_positions = kwargs['replicated_positions']
        self.supercell = kwargs['supercell']
        try:
            self.value = kwargs['value']
        except KeyError:
            self.value = None

        self._replicated_atoms = None
        self.replicated_positions = replicated_positions.reshape(
            (-1, self.atoms.positions.shape[0], self.atoms.positions.shape[1]))
        self.n_replicas = np.prod(self.supercell)
        self._cell_inv = None
        self._replicated_cell_inv = None
        self._list_of_replicas = None
        n_replicas, n_unit_atoms, _ = self.replicated_positions.shape
        atoms_positions = self.atoms.positions
        detected_grid = np.round(
            (replicated_positions.reshape((n_replicas, n_unit_atoms, 3)) -
             atoms_positions[np.newaxis, :, :]).dot(
                 np.linalg.inv(self.atoms.cell))[:, 0, :], 0).astype(np.int)

        grid_c = Grid(grid_shape=self.supercell, order='C')
        grid_fortran = Grid(grid_shape=self.supercell, order='F')
        if (grid_c.grid(is_wrapping=False) == detected_grid).all():
            grid_type = 'C'
            logging.debug("Using C-style position grid")
        elif (grid_fortran.grid(is_wrapping=False) == detected_grid).all():
            grid_type = 'F'
            logging.debug("Using fortran-style position grid")
        else:
            err_msg = "Unable to detect grid type"
            logging.error(err_msg)
            raise TypeError(err_msg)

        self._direct_grid = Grid(self.supercell, grid_type)
Пример #5
0
class Phonons:
    """The Phonons object exposes all the phononic properties of a system.
    It's can be fed into a Conductivity object and must be built with a
    ForceConstant object.

    Parameters
    ----------
    forceconstants : ForceConstants
        contains all the information about the system and the derivatives
        of the potential.
    is_classic : bool
        specifies if the system is classic, `True` or quantum, `False`
        Default is `False`
    kpts : (3) tuple, optional
        defines the number of k points to use to create the k mesh
        Default is (1, 1, 1)
    temperature : float
        defines the temperature of the simulation. Units: K.
    min_frequency : float, optional
        ignores all phonons with frequency below `min_frequency` THz,
        Default is `None`
    max_frequency : float, optional
        ignores all phonons with frequency above `max_frequency` THz
        Default is `None`
    third_bandwidth : float, optional
        Defines the width of the energy conservation smearing in the phonons
        scattering calculation. If `None` the width is calculated
        dynamically. Otherwise the input value corresponds to the width.
        Units: THz.
    broadening_shape : string, optional
        Defines the algorithm to use for the broadening of the conservation
        of the energy for third irder interactions. Available broadenings
        are `gauss`, `lorentz` and `triangle`.
        Default is `gauss`.
    folder : string, optional
        Specifies where to store the data files. Default is `output`.
    storage : `default`, `formatted`, `numpy`, `memory`, `hdf5`, optional
        Defines the storing strategy used to store the observables. The
        `default` strategy stores formatted output and numpy arrays.
        `memory` storage doesn't generate any output.
    grid_type : 'F' or 'C, optional
        Specify if to use 'C" style atoms replica grid of fortran
        style 'F',
        Default 'C'
    is_balanced : Enforce detailed balance when calculating anharmonic properties,
        Default: False

    Returns
    -------
    Phonons Object
    """
    def __init__(self, **kwargs):
        self.forceconstants = kwargs.pop('forceconstants')
        self.is_classic = bool(kwargs.pop('is_classic', False))
        if 'temperature' in kwargs:
            self.temperature = float(kwargs['temperature'])
        self.folder = kwargs.pop('folder', FOLDER_NAME)
        self.kpts = kwargs.pop('kpts', (1, 1, 1))
        self._grid_type = kwargs.pop('grid_type', 'C')
        self._reciprocal_grid = Grid(self.kpts, order=self._grid_type)
        self.is_unfolding = kwargs.pop('is_unfolding', False)
        if self.is_unfolding:
            logging.info('Using unfolding.')
        self.kpts = np.array(self.kpts)
        self.min_frequency = kwargs.pop('min_frequency', 0)
        self.max_frequency = kwargs.pop('max_frequency', None)
        self.broadening_shape = kwargs.pop('broadening_shape', 'gauss')
        self.is_nw = kwargs.pop('is_nw', False)
        self.third_bandwidth = kwargs.pop('third_bandwidth', None)
        self.storage = kwargs.pop('storage', 'formatted')
        self.is_symmetrizing_frequency = kwargs.pop(
            'is_symmetrizing_frequency', False)
        self.is_antisymmetrizing_velocity = kwargs.pop(
            'is_antisymmetrizing_velocity', False)
        self.is_balanced = kwargs.pop('is_balanced', False)
        self.atoms = self.forceconstants.atoms
        self.supercell = np.array(self.forceconstants.supercell)
        self.n_k_points = int(np.prod(self.kpts))
        self.n_atoms = self.forceconstants.n_atoms
        self.n_modes = self.forceconstants.n_modes
        self.n_phonons = self.n_k_points * self.n_modes
        self.is_able_to_calculate = True
        self.hbar = units._hbar
        if self.is_classic:
            self.hbar = self.hbar * 1e-6

    @lazy_property(label='')
    def physical_mode(self):
        """Calculate physical modes. Non physical modes are the first 3 modes of q=(0, 0, 0) and, if defined, all the
        modes outside the frequency range min_frequency and max_frequency.
        Returns
        -------
        physical_mode : np array
            (n_k_points, n_modes) bool
        """
        q_points = self._reciprocal_grid.unitary_grid(is_wrapping=False)
        physical_mode = np.zeros((self.n_k_points, self.n_modes),
                                 dtype=np.bool)

        for ik in range(len(q_points)):
            q_point = q_points[ik]
            phonon = HarmonicWithQ(
                q_point=q_point,
                second=self.forceconstants.second,
                distance_threshold=self.forceconstants.distance_threshold,
                folder=self.folder,
                storage=self.storage,
                is_nw=self.is_nw,
                is_unfolding=self.is_unfolding)

            physical_mode[ik] = phonon.physical_mode
        if self.min_frequency is not None:
            physical_mode[self.frequency < self.min_frequency] = False
        if self.max_frequency is not None:
            physical_mode[self.frequency > self.max_frequency] = False
        return physical_mode

    @lazy_property(label='')
    def frequency(self):
        """Calculate phonons frequency
        Returns
        -------
        frequency : np array
            (n_k_points, n_modes) frequency in THz
        """
        q_points = self._reciprocal_grid.unitary_grid(is_wrapping=False)
        frequency = np.zeros((self.n_k_points, self.n_modes))
        for ik in range(len(q_points)):
            q_point = q_points[ik]
            phonon = HarmonicWithQ(
                q_point=q_point,
                second=self.forceconstants.second,
                distance_threshold=self.forceconstants.distance_threshold,
                folder=self.folder,
                storage=self.storage,
                is_nw=self.is_nw,
                is_unfolding=self.is_unfolding)

            frequency[ik] = phonon.frequency

        return frequency

    @lazy_property(label='')
    def participation_ratio(self):
        """Calculate phonons participation ratio. A value of 1 corresponds to translation.
        Returns
        -------
        participation_ratio : np array
            (n_k_points, n_modes) atomic participation
        """
        q_points = self._reciprocal_grid.unitary_grid(is_wrapping=False)
        participation_ratio = np.zeros((self.n_k_points, self.n_modes))
        for ik in range(len(q_points)):
            q_point = q_points[ik]
            phonon = HarmonicWithQ(
                q_point=q_point,
                second=self.forceconstants.second,
                distance_threshold=self.forceconstants.distance_threshold,
                folder=self.folder,
                storage=self.storage,
                is_nw=self.is_nw,
                is_unfolding=self.is_unfolding)

            participation_ratio[ik] = phonon.participation_ratio

        return participation_ratio

    @lazy_property(label='')
    def velocity(self):
        """Calculates the velocity using Hellmann-Feynman theorem.

        Returns
        -------
        velocity : np array
            (n_k_points, n_unit_cell * 3, 3) velocity in 100m/s or A/ps
        """

        q_points = self._reciprocal_grid.unitary_grid(is_wrapping=False)
        velocity = np.zeros((self.n_k_points, self.n_modes, 3))
        for ik in range(len(q_points)):
            q_point = q_points[ik]
            phonon = HarmonicWithQ(
                q_point=q_point,
                second=self.forceconstants.second,
                distance_threshold=self.forceconstants.distance_threshold,
                folder=self.folder,
                storage=self.storage,
                is_nw=self.is_nw,
                is_unfolding=self.is_unfolding)
            velocity[ik] = phonon.velocity
        return velocity

    @lazy_property(label='')
    def _eigensystem(self):
        """Calculate the eigensystems, for each k point in k_points.

        Returns
        -------
        _eigensystem : np.array(n_k_points, n_unit_cell * 3, n_unit_cell * 3 + 1)
            eigensystem is calculated for each k point, the three dimensional array
            records the eigenvalues in the last column of the last dimension.

            If the system is not amorphous, these values are stored as complex numbers.
        """
        q_points = self._reciprocal_grid.unitary_grid(is_wrapping=False)
        shape = (self.n_k_points, self.n_modes + 1, self.n_modes)
        log_size(shape, name='eigensystem', type=np.complex)
        eigensystem = np.zeros(shape, dtype=np.complex)
        for ik in range(len(q_points)):
            q_point = q_points[ik]
            phonon = HarmonicWithQ(
                q_point=q_point,
                second=self.forceconstants.second,
                distance_threshold=self.forceconstants.distance_threshold,
                folder=self.folder,
                storage=self.storage,
                is_nw=self.is_nw,
                is_unfolding=self.is_unfolding)

            eigensystem[ik] = phonon._eigensystem

        return eigensystem

    @lazy_property(label='<temperature>/<statistics>')
    def heat_capacity(self):
        """Calculate the heat capacity for each k point in k_points and each mode.
        If classical, it returns the Boltzmann constant in W/m/K. If quantum it returns the derivative of the
        Bose-Einstein weighted by each phonons energy.
        .. math::

            c_\\mu = k_B \\frac{\\nu_\\mu^2}{ \\tilde T^2} n_\\mu (n_\\mu + 1)

        where the frequency :math:`\\nu` and the temperature :math:`\\tilde T` are in THz.

        Returns
        -------
        c_v : np.array(n_k_points, n_modes)
            heat capacity in W/m/K for each k point and each mode
        """
        q_points = self._reciprocal_grid.unitary_grid(is_wrapping=False)
        c_v = np.zeros((self.n_k_points, self.n_modes))
        for ik in range(len(q_points)):
            q_point = q_points[ik]
            phonon = HarmonicWithQTemp(
                q_point=q_point,
                second=self.forceconstants.second,
                distance_threshold=self.forceconstants.distance_threshold,
                folder=self.folder,
                storage=self.storage,
                temperature=self.temperature,
                is_classic=self.is_classic,
                is_nw=self.is_nw,
                is_unfolding=self.is_unfolding)
            c_v[ik] = phonon.heat_capacity
        return c_v

    @lazy_property(label='<temperature>/<statistics>')
    def heat_capacity_2d(self):
        """Calculate the generalized 2d heat capacity for each k point in k_points and each mode.
        If classical, it returns the Boltzmann constant in W/m/K.

        Returns
        -------
        heat_capacity_2d : np.array(n_k_points, n_modes, n_modes)
            heat capacity in W/m/K for each k point and each modes couple.
        """
        q_points = self._reciprocal_grid.unitary_grid(is_wrapping=False)
        shape = (self.n_k_points, self.n_modes, self.n_modes)
        log_size(shape, name='heat_capacity_2d', type=np.float)
        heat_capacity_2d = np.zeros(shape)
        for ik in range(len(q_points)):
            q_point = q_points[ik]
            phonon = HarmonicWithQTemp(
                q_point=q_point,
                second=self.forceconstants.second,
                distance_threshold=self.forceconstants.distance_threshold,
                folder=self.folder,
                storage=self.storage,
                temperature=self.temperature,
                is_classic=self.is_classic,
                is_nw=self.is_nw,
                is_unfolding=self.is_unfolding)
            heat_capacity_2d[ik] = phonon.heat_capacity_2d
        return heat_capacity_2d

    @lazy_property(label='<temperature>/<statistics>')
    def population(self):
        """Calculate the phonons population for each k point in k_points and each mode.
        If classical, it returns the temperature divided by each frequency, using equipartition theorem.
        If quantum it returns the Bose-Einstein distribution

        Returns
        -------
        population : np.array(n_k_points, n_modes)
            population for each k point and each mode
        """
        q_points = self._reciprocal_grid.unitary_grid(is_wrapping=False)
        population = np.zeros((self.n_k_points, self.n_modes))
        for ik in range(len(q_points)):
            q_point = q_points[ik]
            phonon = HarmonicWithQTemp(
                q_point=q_point,
                second=self.forceconstants.second,
                distance_threshold=self.forceconstants.distance_threshold,
                folder=self.folder,
                storage=self.storage,
                temperature=self.temperature,
                is_classic=self.is_classic,
                is_nw=self.is_nw,
                is_unfolding=self.is_unfolding)
            population[ik] = phonon.population
        return population

    @lazy_property(label='<temperature>/<statistics>/<third_bandwidth>')
    def bandwidth(self):
        """Calculate the phonons bandwidth, the inverse of the lifetime, for each k point in k_points and each mode.

        Returns
        -------
        bandwidth : np.array(n_k_points, n_modes)
            bandwidth for each k point and each mode
        """
        gamma = self._ps_and_gamma[:, 1].reshape(self.n_k_points, self.n_modes)
        return gamma

    @lazy_property(label='<temperature>/<statistics>/<third_bandwidth>')
    def phase_space(self):
        """Calculate the 3-phonons-processes phase_space, for each k point in k_points and each mode.

        Returns
        -------
        phase_space : np.array(n_k_points, n_modes)
            phase_space for each k point and each mode
        """
        ps = self._ps_and_gamma[:, 0].reshape(self.n_k_points, self.n_modes)
        return ps

    @lazy_property(label='')
    def eigenvalues(self):
        """Calculates the eigenvalues of the dynamical matrix in Thz^2.

        Returns
        -------
        eigenvalues : np array
            (n_phonons) Eigenvalues of the dynamical matrix
        """
        eigenvalues = self._eigensystem[:, 0, :]
        return eigenvalues

    @property
    def eigenvectors(self):
        """Calculates the eigenvectors of the dynamical matrix.

        Returns
        -------
        eigenvectors : np array
            (n_phonons, n_phonons) Eigenvectors of the dynamical matrix
        """
        eigenvectors = self._eigensystem[:, 1:, :]
        return eigenvectors

    @lazy_property(label='<temperature>/<statistics>/<third_bandwidth>')
    def _ps_and_gamma(self):
        store_format = DEFAULT_STORE_FORMATS['_ps_gamma_and_gamma_tensor'] \
            if self.storage == 'formatted' else self.storage
        if is_calculated('_ps_gamma_and_gamma_tensor', self, '<temperature>/<statistics>/<third_bandwidth>', \
                         format=store_format):
            ps_and_gamma = self._ps_gamma_and_gamma_tensor[:, :2]
        else:
            ps_and_gamma = self._select_algorithm_for_phase_space_and_gamma(
                is_gamma_tensor_enabled=False)
        return ps_and_gamma

    @lazy_property(label='<temperature>/<statistics>/<third_bandwidth>')
    def _ps_gamma_and_gamma_tensor(self):
        ps_gamma_and_gamma_tensor = self._select_algorithm_for_phase_space_and_gamma(
            is_gamma_tensor_enabled=True)
        return ps_gamma_and_gamma_tensor

# Helpers properties

    @property
    def omega(self):
        """Calculates the angular frequencies from the diagonalized dynamical matrix.

        Returns
        -------
        frequency : np array
            (n_k_points, n_modes) frequency in rad
        """
        return self.frequency * 2 * np.pi

    @property
    def _rescaled_eigenvectors(self):
        n_atoms = self.n_atoms
        n_modes = self.n_modes
        masses = self.atoms.get_masses()
        rescaled_eigenvectors = self.eigenvectors[:, :, :].reshape(
            (self.n_k_points, n_atoms, 3, n_modes)) / np.sqrt(
                masses[np.newaxis, :, np.newaxis, np.newaxis])
        rescaled_eigenvectors = rescaled_eigenvectors.reshape(
            (self.n_k_points, n_modes, n_modes))
        return rescaled_eigenvectors

    @property
    def _is_amorphous(self):
        is_amorphous = (self.kpts == (1, 1, 1)).all()
        return is_amorphous

    def _allowed_third_phonons_index(self, index_q, is_plus):
        q_vec = self._reciprocal_grid.id_to_unitary_grid_index(index_q)
        qp_vec = self._reciprocal_grid.unitary_grid(is_wrapping=False)
        qpp_vec = q_vec[np.newaxis, :] + (int(is_plus) * 2 - 1) * qp_vec[:, :]
        rescaled_qpp = np.round((qpp_vec * self._reciprocal_grid.grid_shape),
                                0).astype(np.int)
        rescaled_qpp = np.mod(rescaled_qpp, self._reciprocal_grid.grid_shape)
        index_qpp_full = np.ravel_multi_index(rescaled_qpp.T,
                                              self._reciprocal_grid.grid_shape,
                                              mode='raise',
                                              order=self._grid_type)
        return index_qpp_full

    def _select_algorithm_for_phase_space_and_gamma(
            self, is_gamma_tensor_enabled=True):
        self.n_k_points = np.prod(self.kpts)
        self.n_phonons = self.n_k_points * self.n_modes
        self.is_gamma_tensor_enabled = is_gamma_tensor_enabled
        if self._is_amorphous:
            ps_and_gamma = aha.project_amorphous(self)
        else:
            ps_and_gamma = aha.project_crystal(self)
        return ps_and_gamma
Пример #6
0
def read_third_order_matrix_2(third_file, atoms, third_supercell, order='C'):
    supercell = third_supercell
    n_unit_atoms = atoms.positions.shape[0]
    n_replicas = np.prod(supercell)
    current_grid = Grid(third_supercell, order=order).grid(is_wrapping=True)
    list_of_index = current_grid
    list_of_replicas = list_of_index.dot(atoms.cell)
    replicated_cell = atoms.cell * supercell
    # replicated_cell_inv = np.linalg.inv(replicated_cell)

    coords = []
    data = []
    second_cell_positions = []
    third_cell_positions = []
    atoms_coords = []
    sparse_data = []
    with open(third_file, 'r') as file:
        line = file.readline()
        n_third = int(line)
        for i in range(n_third):
            file.readline()
            file.readline()

            second_cell_position = np.fromstring(file.readline(),
                                                 dtype=np.float,
                                                 sep=' ')
            second_cell_positions.append(second_cell_position)
            d_1 = list_of_replicas[:, :] - second_cell_position[np.newaxis, :]
            # d_1 = wrap_coordinates(d_1,  replicated_cell, replicated_cell_inv)

            mask_second = np.linalg.norm(d_1, axis=1) < 1e-5
            second_cell_id = np.argwhere(mask_second).flatten()

            third_cell_position = np.fromstring(file.readline(),
                                                dtype=np.float,
                                                sep=' ')
            third_cell_positions.append(third_cell_position)
            d_2 = list_of_replicas[:, :] - third_cell_position[np.newaxis, :]
            # d_2 = wrap_coordinates(d_2,  replicated_cell, replicated_cell_inv)
            mask_third = np.linalg.norm(d_2, axis=1) < 1e-5
            third_cell_id = np.argwhere(mask_third).flatten()

            atom_i, atom_j, atom_k = np.fromstring(
                file.readline(), dtype=np.int, sep=' ') - 1
            atoms_coords.append([atom_i, atom_j, atom_k])
            small_data = []
            for _ in range(27):

                values = np.fromstring(file.readline(),
                                       dtype=np.float,
                                       sep=' ')
                alpha, beta, gamma = values[:3].round(0).astype(int) - 1
                coords.append([
                    atom_i, alpha, second_cell_id, atom_j, beta, third_cell_id,
                    atom_k, gamma
                ])
                data.append(values[3])
                small_data.append(values[3])
            sparse_data.append(small_data)

    third_order = COO(np.array(coords).T,
                      np.array(data),
                      shape=(n_unit_atoms, 3, n_replicas, n_unit_atoms, 3,
                             n_replicas, n_unit_atoms, 3))
    third_order = third_order.reshape(
        (n_unit_atoms * 3, n_replicas * n_unit_atoms * 3,
         n_replicas * n_unit_atoms * 3))
    return third_order, np.array(sparse_data), np.array(
        second_cell_positions), np.array(third_cell_positions), np.array(
            atoms_coords)
Пример #7
0
class ForceConstant(Observable):

    def __init__(self, *kargs, **kwargs):
        Observable.__init__(self, *kargs, **kwargs)
        self.atoms = kwargs['atoms']
        replicated_positions = kwargs['replicated_positions']
        self.supercell = kwargs['supercell']
        try:
            self.value = kwargs['value']
        except KeyError:
            self.value = None

        self._replicated_atoms = None
        self.replicated_positions = replicated_positions.reshape(
            (-1, self.atoms.positions.shape[0], self.atoms.positions.shape[1]))
        self.n_replicas = np.prod(self.supercell)
        self._cell_inv = None
        self._replicated_cell_inv = None
        self._list_of_replicas = None
        n_replicas, n_unit_atoms, _ = self.replicated_positions.shape
        atoms_positions = self.atoms.positions
        detected_grid = np.round(
            (replicated_positions.reshape((n_replicas, n_unit_atoms, 3)) - atoms_positions[np.newaxis, :, :]).dot(
                np.linalg.inv(self.atoms.cell))[:, 0, :], 0).astype(np.int)

        grid_c = Grid(grid_shape=self.supercell, order='C')
        grid_fortran = Grid(grid_shape=self.supercell, order='F')
        if (grid_c.grid(is_wrapping=False) == detected_grid).all():
            grid_type = 'C'
            logging.debug("Using C-style position grid")
        elif (grid_fortran.grid(is_wrapping=False) == detected_grid).all():
            grid_type = 'F'
            logging.debug("Using fortran-style position grid")
        else:
            err_msg = "Unable to detect grid type"
            logging.error(err_msg)
            raise TypeError(err_msg)

        self._direct_grid = Grid(self.supercell, grid_type)


    @classmethod
    def from_supercell(cls, atoms, supercell, grid_type, value=None, folder='kALDo'):
        _direct_grid = Grid(supercell, grid_type)
        replicated_positions = _direct_grid.grid(is_wrapping=False).dot(atoms.cell)[:, np.newaxis, :] + atoms.positions[
                                                                                       np.newaxis, :, :]
        inst = cls(atoms=atoms,
                   replicated_positions=replicated_positions,
                   supercell=supercell,
                   value=value,
                   folder=folder)
        inst._direct_grid = _direct_grid
        return inst


    @property
    def positions(self):
        return self.atoms.positions


    @property
    def cell_inv(self):
        if self._cell_inv is None:
            self._cell_inv = np.linalg.inv(self.atoms.cell)
        return self._cell_inv


    @property
    def replicated_atoms(self):
        # TODO: remove this method
        if self._replicated_atoms is None:
            supercell = self.supercell
            atoms = self.atoms
            replicated_atoms = atoms.copy() * supercell
            replicated_positions = self._direct_grid.grid(is_wrapping=False).dot(atoms.cell)[:, np.newaxis, :] + atoms.positions[
                                                                                                np.newaxis, :, :]
            replicated_atoms.set_positions(replicated_positions.reshape(-1, 3))
            self._replicated_atoms = replicated_atoms
        return self._replicated_atoms


    @property
    def replicated_cell_inv(self):
        if self._replicated_cell_inv is None:
            self._replicated_cell_inv = np.linalg.inv(self.replicated_atoms.cell)
        return self._replicated_cell_inv


    @property
    def list_of_replicas(self):
        if self._list_of_replicas is None:
            list_of_index = self._direct_grid.grid(is_wrapping=True)
            self._list_of_replicas = list_of_index.dot(self.atoms.cell)
        return self._list_of_replicas


    def _chi_k(self, k_points):
        n_k_points = np.shape(k_points)[0]
        ch = np.zeros((n_k_points, self.n_replicas), dtype=np.complex)
        for index_q in range(n_k_points):
            k_point = k_points[index_q]

            list_of_replicas = self.list_of_replicas
            cell_inv = self.cell_inv
            ch[index_q] = chi(k_point, list_of_replicas, cell_inv)
        return ch