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
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
def participation_ratio(self): """Calculates the participation ratio of each normal mode. Participation ratio's represent the fraction of atoms that are displaced meaning a value of 1 corresponds to translation. Defined by equations in DOI: 10.1103/PhysRevB.53.11469 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
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_unfolding=self.is_unfolding) velocity[ik] = phonon.velocity return velocity
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_unfolding=self.is_unfolding) frequency[ik] = phonon.frequency return frequency
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
def plot_dispersion(phonons, n_k_points=300, is_showing=True, symprec=1e-3, is_nw=None, with_velocity=True, color='b', is_unfolding=False): atoms = phonons.atoms if is_nw is None and phonons.is_nw: is_nw = phonons.is_nw if is_nw: q = np.linspace(0, 0.5, n_k_points) k_list = np.zeros((n_k_points, 3)) k_list[:, 0] = q k_list[:, 2] = q Q = [0, 0.5] point_names = ['$\\Gamma$', 'X'] else: try: k_list, Q, point_names = create_k_and_symmetry_space( atoms, n_k_points=n_k_points, symprec=symprec) q = np.linspace(0, 1, k_list.shape[0]) except seekpath.hpkot.SymmetryDetectionError as err: print(err) q = np.linspace(0, 0.5, n_k_points) k_list = np.zeros((n_k_points, 3)) k_list[:, 0] = q k_list[:, 2] = q Q = [0, 0.5] point_names = ['$\\Gamma$', 'X'] freqs_plot = [] vel_plot = [] vel_norm = [] for q_point in k_list: phonon = HarmonicWithQ( q_point, phonons.forceconstants.second, distance_threshold=phonons.forceconstants.distance_threshold, storage='memory', is_unfolding=is_unfolding) freqs_plot.append(phonon.frequency.flatten()) if with_velocity: val_value = phonon.velocity[0] vel_plot.append(val_value) vel_norm.append(np.linalg.norm(val_value, axis=-1)) freqs_plot = np.array(freqs_plot) if with_velocity: vel_plot = np.array(vel_plot) vel_norm = np.array(vel_norm) fig1, ax1 = plt.subplots() plt.tick_params(axis='both', which='minor', labelsize=16) plt.ylabel("$\\nu$ (THz)", fontsize=16) plt.xlabel('$q$', fontsize=16) plt.tick_params(axis='both', which='major', labelsize=16) plt.xticks(Q, point_names) plt.xlim(q[0], q[-1]) if color is not None: plt.plot(q, freqs_plot, '.', color=color, linewidth=4, markersize=4) else: plt.plot(q, freqs_plot, '.', linewidth=4, markersize=4) plt.grid() plt.ylim(freqs_plot.min(), freqs_plot.max() * 1.05) folder = get_folder_from_label(phonons, base_folder=DEFAULT_FOLDER) if not os.path.exists(folder): os.makedirs(folder) plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1) fig1.savefig(folder + '/' + 'dispersion' + '.png') np.savetxt(folder + '/' + 'q', q) np.savetxt(folder + '/' + 'dispersion', freqs_plot) if is_showing: plt.show() else: plt.close() if with_velocity: for alpha in range(3): np.savetxt(folder + '/' + 'velocity_' + str(alpha), vel_plot[:, :, alpha]) fig2, ax2 = plt.subplots() plt.ylabel('$|v|(\AA/ps)$', fontsize=16) plt.xlabel('$q$', fontsize=16) plt.tick_params(axis='both', which='major', labelsize=16) plt.tick_params(axis='both', which='minor', labelsize=20) plt.xticks(Q, point_names) plt.xlim(q[0], q[-1]) if color is not None: plt.plot(q, vel_norm[:, :], '.', linewidth=4, markersize=4, color=color) else: plt.plot(q, vel_norm[:, :], '.', linewidth=4, markersize=4) plt.grid() plt.tick_params(axis='both', which='major', labelsize=16) fig2.savefig(folder + '/' + 'velocity.png') np.savetxt(folder + '/' + 'velocity_norm', vel_norm) if is_showing: plt.show() else: plt.close()