def get_renormalized_force_constants(renormalized_frequencies, eigenvectors, structure, fc_supercell, symmetrize=False): phonon = get_phonon(structure, setup_forces=False, custom_supercell=fc_supercell) primitive = phonon.get_primitive() supercell = phonon.get_supercell() dynmat2fc = DynmatToForceConstants(primitive, supercell) size = structure.get_number_of_dimensions() * structure.get_number_of_primitive_atoms() eigenvectors = np.array([eigenvector.reshape(size, size, order='C').T for eigenvector in eigenvectors ]) renormalized_frequencies = np.array(renormalized_frequencies) try: dynmat2fc.set_dynamical_matrices(renormalized_frequencies / VaspToTHz, eigenvectors) except TypeError: dynmat2fc.create_dynamical_matrices(frequencies=renormalized_frequencies / VaspToTHz, eigenvalues=None, eigenvectors=eigenvectors) dynmat2fc.run() force_constants = ForceConstants(dynmat2fc.get_force_constants(), supercell=fc_supercell) # Symmetrize force constants using crystal symmetry if symmetrize: print('Symmetrizing force constants') set_tensor_symmetry_PJ(force_constants.get_array(), phonon.supercell.get_cell(), phonon.supercell.get_scaled_positions(), phonon.symmetry) return force_constants
def run_correlation_matrix(self, T): """Calculate displacement-displacement correlation matrix.""" qpoints, eigvals, eigvecs = self._collect_eigensolutions() d2f = DynmatToForceConstants(self._dynmat.primitive, self._dynmat.supercell) masses = self._dynmat.supercell.masses d2f.commensurate_points = qpoints freqs = np.sqrt(np.abs(eigvals)) * self._factor conditions = freqs > self._cutoff_frequency a = self._get_sigma(eigvals, T) a2 = a**2 _a = np.where(conditions, a, 1) a2_inv = np.where(conditions, 1 / _a**2, 0) d2f.create_dynamical_matrices(a2_inv, eigvecs) d2f.run() self._uu_inv = np.array(d2f.force_constants, dtype="double", order="C") d2f.create_dynamical_matrices(a2, eigvecs) d2f.run() matrix = d2f.force_constants for i, m_i in enumerate(masses): for j, m_j in enumerate(masses): matrix[i, j] /= m_i * m_j self._uu = np.array(matrix, dtype="double", order="C")
def run_d2f(self): qpoints, eigvals, eigvecs = self._collect_eigensolutions() d2f = DynmatToForceConstants(self._dynmat.primitive, self._dynmat.supercell) d2f.commensurate_points = qpoints d2f.create_dynamical_matrices(eigvals, eigvecs) d2f.run() self._force_constants = d2f.force_constants
def test_with_eigenvalues(ph_nacl, ph_nacl_nonac): for ph in (ph_nacl_nonac, ph_nacl): d2f = DynmatToForceConstants(ph.primitive, ph.supercell) ph.run_qpoints(d2f.commensurate_points, with_eigenvectors=True, with_dynamical_matrices=True) ph_dict = ph.get_qpoints_dict() eigenvalues = ((ph_dict['frequencies'] / VaspToTHz) ** 2 * np.sign(ph_dict['frequencies'])) d2f.create_dynamical_matrices(eigenvalues=eigenvalues, eigenvectors=ph_dict['eigenvectors']) d2f.run() np.testing.assert_allclose(ph.force_constants, d2f.force_constants, atol=1e-5)
def test_with_eigenvalues(ph_nacl, ph_nacl_nonac): """Test transformation from eigensolutions to dynamical matrix.""" for ph in (ph_nacl_nonac, ph_nacl): d2f = DynmatToForceConstants(ph.primitive, ph.supercell) ph.run_qpoints( d2f.commensurate_points, with_eigenvectors=True, with_dynamical_matrices=True, ) ph_dict = ph.get_qpoints_dict() eigenvalues = (ph_dict["frequencies"] / VaspToTHz)**2 * np.sign( ph_dict["frequencies"]) d2f.create_dynamical_matrices(eigenvalues=eigenvalues, eigenvectors=ph_dict["eigenvectors"]) d2f.run() np.testing.assert_allclose(ph.force_constants, d2f.force_constants, atol=1e-5)
class DispCorrMatrixMesh(object): """Calculate upsilon and psi matrix This calculation is similar to the transformation from dynamical matrices to force constants. Instead of creating dynamcial matrices from eigenvalues and eigenvectors, 1/a**2 or a**2 and eigenvectors are used, where a is mode length. psi_matrix : ndarray Displacement-displacement correlation matrix at temperature. Physical unit is [Angstrom^2]. shape=(3 * num_satom, 3 * num_satom), dtype='double', order='C' upsilon_matrix : ndarray Inverse displacement-displacement correlation matrix at temperature. Physical unit is [1/Angstrom^2]. shape=(3 * num_satom, 3 * num_satom), dtype='double', order='C' commensurate_points : ndarray Commensurate q-points of transformation matrix from primitive cell to supercell. shape=(det(transformation_matrix), 3), dtype='double', order='C'. """ def __init__(self, primitive, supercell, cutoff_frequency=1e-5): self._d2f = DynmatToForceConstants(primitive, supercell, is_full_fc=True) self._masses = supercell.masses self._cutoff_frequency = cutoff_frequency self._psi_matrix = None self._upsilon_matrix = None @property def commensurate_points(self): return self._d2f.commensurate_points def run(self, frequencies, eigenvectors, T): """ Parameters ---------- frequencies : ndarray Supercell phonon frequencies in THz (without 2pi). shape=(grid_point, band), dtype='double', order='C' eigenvectors : ndarray Supercell phonon eigenvectors. shape=(grid_point, band, band), dtype='double', order='C' """ condition = frequencies > self._cutoff_frequency _freqs = np.where(condition, frequencies, 1) _a = mode_length(_freqs, T) a2 = np.where(condition, _a**2, 0) a2_inv = np.where(condition, 1 / _a**2, 0) N = len(self._masses) shape = (N * 3, N * 3) self._d2f.create_dynamical_matrices(a2_inv, eigenvectors) self._d2f.run() matrix = self._d2f.force_constants matrix = np.transpose(matrix, axes=[0, 2, 1, 3]).reshape(shape) self._upsilon_matrix = np.array(matrix, dtype='double', order='C') self._d2f.create_dynamical_matrices(a2, eigenvectors) self._d2f.run() matrix = self._d2f.force_constants for i, m_i in enumerate(self._masses): for j, m_j in enumerate(self._masses): matrix[i, j] /= m_i * m_j matrix = np.transpose(matrix, axes=[0, 2, 1, 3]).reshape(shape) self._psi_matrix = np.array(matrix, dtype='double', order='C') @property def upsilon_matrix(self): return self._upsilon_matrix @property def psi_matrix(self): return self._psi_matrix