def make_Gonze_nac_dataset(self): """Prepare Gonze-Lee force constants. Dipole-dipole interaction contribution is subtracted from supercell force constants. """ try: import phonopy._phonopy as phonoc # noqa F401 self._run_c_recip_dipole_dipole_q0() except ImportError: print("Python version of dipole-dipole calculation is not well " "implemented.") sys.exit(1) fc_shape = self._force_constants.shape d2f = DynmatToForceConstants(self._pcell, self._scell, is_full_fc=(fc_shape[0] == fc_shape[1])) dynmat = [] num_q = len(d2f.commensurate_points) for i, q_red in enumerate(d2f.commensurate_points): if self._log_level > 2: print("%d/%d %s" % (i + 1, num_q, q_red)) self._run(q_red) dm_dd = self._get_Gonze_dipole_dipole(q_red, None) self._dynamical_matrix -= dm_dd dynmat.append(self._dynamical_matrix) d2f.dynamical_matrices = dynmat d2f.run() self._Gonze_force_constants = d2f.force_constants self._Gonze_count = 0
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
def test_with_dynamical_matrices(ph_nacl, ph_nacl_nonac): for ph in (ph_nacl, ph_nacl_nonac): d2f = DynmatToForceConstants(ph.primitive, ph.supercell) ph.run_qpoints(d2f.commensurate_points, with_dynamical_matrices=True) ph_dict = ph.get_qpoints_dict() d2f.dynamical_matrices = ph_dict['dynamical_matrices'] d2f.run() np.testing.assert_allclose(ph.force_constants, d2f.force_constants, atol=1e-5)
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 get_commensurate_points(structure, fc_supercell): phonon = get_phonon(structure, setup_forces=False, custom_supercell=fc_supercell) primitive = phonon.get_primitive() supercell = phonon.get_supercell() dynmat2fc = DynmatToForceConstants(primitive, supercell) com_points = dynmat2fc.get_commensurate_points() return com_points
def get_commensurate_points_info(structure): phonon = get_phonon(structure) primitive = phonon.get_primitive() supercell = phonon.get_supercell() dynmat2fc = DynmatToForceConstants(primitive, supercell) com_points = dynmat2fc.get_commensurate_points() phonon.set_qpoints_phonon(com_points, is_eigenvectors=True) return com_points, dynmat2fc, phonon
def phonopy_commensurate_shifts_inline(**kwargs): from phonopy.structure.atoms import Atoms as PhonopyAtoms from phonopy import Phonopy from phonopy.harmonic.dynmat_to_fc import get_commensurate_points, DynmatToForceConstants structure = kwargs.pop('structure') phonopy_input = kwargs.pop('phonopy_input').get_dict() force_constants = kwargs.pop('force_constants').get_array('force_constants') r_force_constants = kwargs.pop('r_force_constants').get_array('force_constants') # Generate phonopy phonon object bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites], positions=[site.position for site in structure.sites], cell=structure.cell) phonon = Phonopy(bulk, phonopy_input['supercell'], primitive_matrix=phonopy_input['primitive'], distance=phonopy_input['distance']) primitive = phonon.get_primitive() supercell = phonon.get_supercell() phonon.set_force_constants(force_constants) dynmat2fc = DynmatToForceConstants(primitive, supercell) com_points = dynmat2fc.get_commensurate_points() phonon.set_qpoints_phonon(com_points, is_eigenvectors=True) frequencies_h = phonon.get_qpoints_phonon()[0] phonon.set_force_constants(r_force_constants) phonon.set_qpoints_phonon(com_points, is_eigenvectors=True) frequencies_r = phonon.get_qpoints_phonon()[0] shifts = frequencies_r - frequencies_h # Stores DOS data in DB as a workflow result commensurate = ArrayData() commensurate.set_array('qpoints', com_points) commensurate.set_array('shifts', shifts) return {'commensurate': commensurate}
def test_with_dynamical_matrices(ph_nacl, ph_nacl_nonac, is_nac, lang): """Test transformation from dynamical matrix to force constants.""" if is_nac: ph = ph_nacl else: ph = ph_nacl_nonac d2f = DynmatToForceConstants(ph.primitive, ph.supercell) ph.run_qpoints(d2f.commensurate_points, with_dynamical_matrices=True) ph_dict = ph.get_qpoints_dict() d2f.dynamical_matrices = ph_dict["dynamical_matrices"] d2f.run(lang=lang) np.testing.assert_allclose(ph.force_constants, d2f.force_constants, atol=1e-5)
def _run_Gonze_force_constants(self): fc_shape = self._force_constants.shape d2f = DynmatToForceConstants(self._pcell, self._scell, is_full_fc=(fc_shape[0] == fc_shape[1])) dynmat = [] num_q = len(d2f.commensurate_points) for i, q_red in enumerate(d2f.commensurate_points): if self._log_level > 2: print("%d/%d %s" % (i + 1, num_q, q_red)) self._run(q_red) dm_dd = self._get_Gonze_dipole_dipole(q_red, None) self._dynamical_matrix -= dm_dd dynmat.append(self._dynamical_matrix) d2f.dynamical_matrices = dynmat d2f.run() self._Gonze_force_constants = d2f.force_constants
def get_commensurate(structure, ph_settings): from phonopy import Phonopy from phonopy.harmonic.dynmat_to_fc import DynmatToForceConstants from aiida_phonopy.workchains.phonon import phonopy_bulk_from_structure phonon = Phonopy(phonopy_bulk_from_structure(structure), ph_settings.dict.supercell, primitive_matrix=ph_settings.dict.primitive, symprec=ph_settings.dict.symmetry_precision) primitive = phonon.get_primitive() supercell = phonon.get_supercell() dynmat2fc = DynmatToForceConstants(primitive, supercell) commensurate = dynmat2fc.get_commensurate_points() return dynmat2fc, commensurate
def get_force_constants(phonon_origin, gruneisen, commensurate, volumes): from phonopy.harmonic.dynmat_to_fc import DynmatToForceConstants from phonopy.units import VaspToTHz from copy import deepcopy phonon = deepcopy(phonon_origin) phonon.set_qpoints_phonon(commensurate, is_eigenvectors=True) frequencies, eigenvectors = phonon.get_qpoints_phonon() primitive = phonon.get_primitive() supercell = phonon.get_supercell() dynmat2fc = DynmatToForceConstants(primitive, supercell) volume_ref = phonon.get_unitcell().get_volume() force_constants_list = [] for volume in volumes: renormalized_frequencies = [] for freq, g in zip(frequencies, gruneisen): renormalized_frequencies.append(freq + (freq * (np.exp(-g*np.log(volume/volume_ref))-1))) renormalized_frequencies = np.array(renormalized_frequencies) # Fixing Gamma point data renormalized_frequencies[0][0:3] = [0.0, 0.0, 0.0] dynmat2fc.set_dynamical_matrices(renormalized_frequencies / VaspToTHz, eigenvectors) dynmat2fc.run() force_constants_list.append(np.array(dynmat2fc.get_force_constants())) return force_constants_list
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 _set_Gonze_force_constants(self): d2f = DynmatToForceConstants(self._pcell, self._scell, symprec=self._symprec) self._force_constants = self._bare_force_constants dynmat = [] num_q = len(d2f.get_commensurate_points()) for i, q_red in enumerate(d2f.get_commensurate_points()): print("%d/%d %s" % (i + 1, num_q, q_red)) self._set_dynamical_matrix(q_red) dm_dd = self._get_Gonze_dipole_dipole(q_red, None) self._dynamical_matrix -= dm_dd dynmat.append(self._dynamical_matrix) d2f.set_dynamical_matrices(dynmat=dynmat) d2f.run() self._Gonze_force_constants = d2f.get_force_constants()
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) dynmat2fc.set_dynamical_matrices(renormalized_frequencies / VaspToTHz, 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_d2f(self): N = len(self._comm_points) if self._ij: eigvals = np.vstack( (self._eigvals_ii, self._eigvals_ij, self._eigvals_ij)) eigvecs = np.vstack( (self._eigvecs_ii, self._eigvecs_ij, self._eigvecs_ij)) eigvecs[-len(self._ij):] = eigvecs[-len(self._ij):].conj() qpoints = self._comm_points[self._ii + self._ij * 2] / float(N) qpoints[-len(self._ij):] = -qpoints[-len(self._ij):] else: eigvals = self._eigvals_ii eigvecs = self._eigvecs_ii qpoints = self._comm_points[self._ii] / float(N) d2f = DynmatToForceConstants(self._dynmat.primitive, self._dynmat.supercell, eigenvalues=eigvals, eigenvectors=eigvecs, commensurate_points=qpoints) d2f.run() self._force_constants = d2f.force_constants
def _set_Gonze_force_constants(self): d2f = DynmatToForceConstants(self._pcell, self._scell, symprec=self._symprec) dynmat = [] num_q = len(d2f.get_commensurate_points()) for i, q_red in enumerate(d2f.get_commensurate_points()): if self._log_level > 1: print("%d/%d %s" % (i + 1, num_q, q_red)) self._set_dynamical_matrix(q_red) dm_dd = self._get_Gonze_dipole_dipole(q_red, None) self._dynamical_matrix -= dm_dd dynmat.append(self._dynamical_matrix) d2f.set_dynamical_matrices(dynmat=dynmat) d2f.run() self._Gonze_force_constants = d2f.get_force_constants()
def get_commensurate_points(structure, phonopy_input): from phonopy.structure.atoms import Atoms as PhonopyAtoms from phonopy.harmonic.dynmat_to_fc import DynmatToForceConstants from phonopy import Phonopy # Generate phonopy phonon object bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites], positions=[site.position for site in structure.sites], cell=structure.cell) phonon = Phonopy(bulk, phonopy_input['supercell'], primitive_matrix=phonopy_input['primitive'], distance=phonopy_input['distance'], symprec=phonopy_input['symmetry_precision']) primitive = phonon.get_primitive() supercell = phonon.get_supercell() dynmat2fc = DynmatToForceConstants(primitive, supercell) com_points = dynmat2fc.get_commensurate_points() return com_points
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)
def phonopy_merge(**kwargs): from phonopy.structure.atoms import Atoms as PhonopyAtoms from phonopy import Phonopy from phonopy.units import VaspToTHz from phonopy.harmonic.dynmat_to_fc import get_commensurate_points, DynmatToForceConstants structure = kwargs.pop('structure') phonopy_input = kwargs.pop('phonopy_input').get_dict() harmonic = kwargs.pop('harmonic') renormalized = kwargs.pop('renormalized') eigenvectors = harmonic.get_array('eigenvectors') frequencies = harmonic.get_array('frequencies') shifts = renormalized.get_array('shifts') # Generate phonopy phonon object bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites], positions=[site.position for site in structure.sites], cell=structure.cell) phonon = Phonopy(bulk, phonopy_input['supercell'], primitive_matrix=phonopy_input['primitive'], distance=phonopy_input['distance']) primitive = phonon.get_primitive() supercell = phonon.get_supercell() total_frequencies = frequencies + shifts dynmat2fc = DynmatToForceConstants(primitive, supercell) dynmat2fc.set_dynamical_matrices(total_frequencies / VaspToTHz, eigenvectors) dynmat2fc.run() total_force_constants = dynmat2fc.get_force_constants() # Stores DOS data in DB as a workflow result total_data = ArrayData() total_data.set_array('force_constants', total_force_constants) return {'final_results': total_data} # Start script here # Workflow phonon (at given volume) wf = load_workflow(431) parameters = wf.get_parameters() results = wf.get_results() inline_params = {'structure': results['final_structure'], 'phonopy_input': parameters['phonopy_input'], 'force_constants': results['force_constants']} harmonic = phonopy_commensurate_inline(**inline_params) # At reference volume (at T = 0) wf = load_workflow(432) parameters = wf.get_parameters() results_r = wf.get_results() results_h = wf.get_results() inline_params = {'structure': results_h['final_structure'], 'phonopy_input': parameters['phonopy_input'], 'force_constants': results_h['force_constants'], 'r_force_constants': results_r['r_force_constants']} renormalized = phonopy_commensurate_shifts_inline(**inline_params) inline_params = {'structure': results_h['final_structure'], 'phonopy_input': parameters['phonopy_input'], 'harmonic': harmonic, 'renormalized': renormalized} total = phonopy_merge(**inline_params) print total inline_params = {'structure': results_h['final_structure'], 'phonopy_input': parameters['phonopy_input'], 'force_constants': total['force_constants']} results = phonopy_calculation_inline(**inline_params)[1] band = results['band_structure'] # Phonon Band structure plot plot_data(results['band_structure'])
band = [] for i in range(51): band.append( np.array(q_start) + (np.array(q_end) - np.array(q_start)) / 50 * i) bands.append(band) bulk = read_vasp("POSCAR") phonon = Phonopy(bulk, [[2, 0, 0], [0, 2, 0], [0, 0, 2]], primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], is_auto_displacements=False) primitive = phonon.get_primitive() supercell = phonon.get_supercell() dynmat2fc = DynmatToForceConstants(primitive, supercell) com_points = dynmat2fc.get_commensurate_points() print "Commensurate points" for i, q in enumerate(com_points): print i + 1, q force_sets = parse_FORCE_SETS() phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() phonon.set_qpoints_phonon(com_points, is_eigenvectors=True) frequencies, eigenvectors = phonon.get_qpoints_phonon() dynmat2fc.set_dynamical_matrices(frequencies / VaspToTHz, eigenvectors) dynmat2fc.run() fc = dynmat2fc.get_force_constants()
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
(np.array(q_end) - np.array(q_start)) / 50 * i) bands.append(band) bulk = read_vasp("POSCAR") phonon = Phonopy(bulk, [[2, 0, 0], [0, 2, 0], [0, 0, 2]], primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], is_auto_displacements=False) primitive = phonon.get_primitive() supercell = phonon.get_supercell() dynmat2fc = DynmatToForceConstants(primitive, supercell) com_points = dynmat2fc.get_commensurate_points() print "Commensurate points" for i, q in enumerate(com_points): print i + 1, q force_sets = parse_FORCE_SETS() phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() phonon.set_qpoints_phonon(com_points, is_eigenvectors=True) frequencies, eigenvectors = phonon.get_qpoints_phonon() dynmat2fc.set_dynamical_matrices(frequencies / VaspToTHz, eigenvectors) dynmat2fc.run() fc = dynmat2fc.get_force_constants()
def BuildForceConstants(lattice_vectors, atom_types, atom_pos, q_pts, freqs, eigs, sc_dim, freq_units = 'thz', atom_mass = None, file_path = r"FORCE_CONSTANTS"): """ Use the Phonopy API to take a set of frequencies and eigenvectors, construct a dynamical matrix, transform to a set of force constants, and write out a Phonopy FORCE_CONSTANTS file. Args: lattice_vectors -- 3x3 matrix containing the lattice vectors atom_types -- list of atomic symbols atom_pos -- list of atomic positions ** in fractional coordinates ** q_pts -- list of q-point coordinates freqs -- n_q sets of Frequencies eigs -- n_q sets of eigenvectors sc_dim -- (equivalent) supercell dimension for preparing force constants freq_units -- units of freqs ('thz' or 'inv_cm' -- default: 'thz') atom_mass -- (optional) list of atomic masses (default: taken from Phonopy internal database) file_path -- path to FORCE_CONSTANTS file to write (default: FORCE_CONSTANTS) """ # Check input. _CheckStructure(lattice_vectors, atom_types, atom_pos, atom_mass) for param in q_pts, freqs, eigs, sc_dim: assert param is not None dim_1, dim_2 = np.shape(q_pts) assert dim_1 > 0 and dim_2 == 3 n_at = len(atom_types) n_q = dim_1 n_b = 3 * n_at dim_1, dim_2 = np.shape(freqs) assert dim_1 == n_q and dim_2 == n_b dim_1, dim_2, dim_3, dim_4 = np.shape(eigs) assert dim_1 == n_q and dim_2 == n_b and dim_3 == n_at and dim_4 == 3 dim_1, = np.shape(sc_dim) assert dim_1 == 3 # Obtain a frequency conversion factor to "VASP units". freq_conv_factor = None if freq_units == 'thz': freq_conv_factor = VaspToTHz elif freq_units == 'inv_cm': freq_conv_factor = VaspToCm if freq_conv_factor is None: raise Exception("Error: Unknown freq_units '{0}'.".format(freq_units)) # Create a Phonopy-format structure. structure = PhonopyAtoms( symbols = atom_types, masses = atom_mass, scaled_positions = atom_pos, cell = lattice_vectors ) # Convert supercell expansion to a supercell matrix. dim_1, dim_2, dim_3 = sc_dim if dim_1 != dim_2 != dim_2 != 1: warnings.warn("The dynamical matrix -> force constants transform has only been tested at the Gamma point; please report issues to the developer.", RuntimeWarning) sc_matrix = [[dim_1, 0, 0], [0, dim_2, 0], [0, 0, dim_3]] # Use the main Phonopy object to obtain the primitive cell and supercell. calculator = Phonopy(structure, sc_matrix) primitive = calculator.get_primitive(); supercell = calculator.get_supercell(); # Use the DynmatToForceConstants object to convert frequencies/eigenvectors -> dynamical matrices -> force constants. dynmat_to_fc = DynmatToForceConstants(primitive, supercell) commensurate_points = dynmat_to_fc.get_commensurate_points() # If an input code does not use crystal symmetry or outputs data at all q-points in a sampling mesh, data may be provided for more q-points than there are commensurate points. # However, for most codes this would be an odd situation -> issue a warning. if len(commensurate_points) != n_q: warnings.warn("The number of entries in the q_pts list does not equal the number of commensurate points expected for the supplied supercell matrix.", RuntimeWarning) # Map commensurate points in Phonopy setup to q-points in input data. map_indices = [] for qx_1, qy_1, qz_1 in commensurate_points: map_index = None for i, (qx_2, qy_2, qz_2) in enumerate(q_pts): if math.fabs(qx_2 - qx_1) < _SymPrec and math.fabs(qy_2 - qy_1) < _SymPrec and math.fabs(qz_2 - qz_1) < _SymPrec: map_index = i break if map_index is None: raise Exception("Error: Expected q = ({0: >6.3f}, {1: >6.3f}, {2: >6.3f}) in the q_pts list (this may be a bug; please report to the developer).".format(qx_1, qy_1, qz_1)) # Sanity check. assert map_index not in map_indices map_indices.append(map_index) # Arrange the frequencies and eigenvectors to the layout required by Phonopy. freq_sets, eig_sets = [], [] for index in map_indices: freq_sets.append( [freq / freq_conv_factor for freq in freqs[index]] ) eig = eigs[index] # Eigenvectors need to be a 3Nx3N matrix in the format: # 1_x -> [ m_1, ..., m_3N ] # 1_y -> [ m_1, ..., m_3N ] # ... # N_z -> [ m_1, ..., m_3N ] eig_rows = [] for i in range(0, n_at): for j in range(0, 3): eig_row = [] for k in range(0, n_b): eig_row.append(eig[k][i][j]) eig_rows.append(eig_row) eig_sets.append(eig_rows) freq_sets = np.array(freq_sets, dtype = np.float64) eig_sets = np.array(eig_sets, dtype = np.complex128) # Use the DynmatToForceConstants object to build the dynamical matrices, reverse transform to the force constants, and write a Phonopy FORCE_CONSTANTS file. dynmat_to_fc.set_dynamical_matrices(freq_sets, eig_sets) dynmat_to_fc.run() write_FORCE_CONSTANTS( dynmat_to_fc.get_force_constants(), filename = file_path )
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")