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 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_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 _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 _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 _set_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]), 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 > 2: 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 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'])
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 )
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() phonon2 = 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) phonon2.set_force_constants(fc) bands = [] append_band(bands, [0.0, 0.0, 0.0], [0.5, 0.0, 0.0]) append_band(bands, [0.5, 0.0, 0.0], [0.5, 0.5, 0.0])
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() phonon2 = 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) phonon2.set_force_constants(fc) bands = [] append_band(bands, [0.0, 0.0, 0.0], [0.5, 0.0, 0.0]) append_band(bands, [0.5, 0.0, 0.0], [0.5, 0.5, 0.0]) append_band(bands, [0.5, 0.5, 0.0], [0.0, 0.0, 0.0]) append_band(bands, [0.0, 0.0, 0.0], [0.5, 0.5, 0.5]) phonon2.set_band_structure(bands) phonon2.plot_band_structure().show()