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 onGrid( qpoints, supercell_matrix, force_constants, freq2omega=THz2meV, poscar='POSCAR', ): """use phonopy to compute phonon frequencies and polarizations for the given Q points on a grid force_constants: instance """ # set up Si crystal lattice bulk = vasp.read_vasp(poscar) # phonopy phonon instance phonon = Phonopy(bulk, supercell_matrix, factor=VaspToTHz) phonon.generate_displacements(distance=0.01) # symmetry = phonon.get_symmetry() # report # print "Space group:", symmetry.get_international_table() # phonon.print_displacements() # supercells = phonon.get_supercells_with_displacements() # set force constants phonon.set_force_constants(force_constants) # calc band structure # . compute phonon.set_qpoints_phonon( qpoints, is_eigenvectors=True, write_dynamical_matrices=False) # , factor=VaspToTHz) # output band structure # phonon.write_yaml_qpoints_phonon() # . get data freq, pols = phonon.get_qpoints_phonon() freq = freq * freq2omega pols = np.transpose(pols, (0, 2, 1)) pols.shape = pols.shape[:-1] + (-1, 3) # pols: Q, branch, atom, xyz print("* Discarding negative freqencies") freq[freq < 0] = 0 # min = np.min(freq) # if min < 0: freq += -min # correction for pols print("* Fixing polarizations") nq, nbr, natoms, three = pols.shape assert three is 3 atoms = vasp.read_vasp(poscar) positions = atoms.get_scaled_positions() # correct polarization vectors # the phase factor is needed. see the notebook tests/phonon/phase-factor.ipynb # c.c. is needed at the very end because of another convention difference between phonopy and pybvk codes. # without c.c., we have to use exp(-j Q dot r) instead of exp(j Q dot r) in calculation of dynamical factors for iatom in range(natoms): qdotr = np.dot(qpoints, positions[iatom]) * 2 * np.pi phase = np.exp(1j * qdotr) pols[:, :, iatom, :] *= phase[:, np.newaxis, np.newaxis] norms = np.linalg.norm(pols, axis=-1) pols /= norms[:, :, :, np.newaxis] continue pols = np.conj(pols) # return qpoints, freq, pols
class PhononFC3Base(TaskElement): """PhononFC3Base class This is an interface to anharmonic phonopy. """ def __init__(self, directory=None, name=None, supercell_matrix=None, primitive_matrix=None, distance=None, is_diagonal=True, check_imaginary=True, cutoff_frequency=None, lattice_tolerance=None, force_tolerance=None, pressure_target=None, stress_tolerance=None, max_increase=None, max_iteration=None, min_iteration=None, is_cell_relaxed=False, traverse=False): TaskElement.__init__(self) self._directory = directory if not name: self._name = directory else: self._name = name self._task_type = "anharmonic_phonon" self._supercell_matrix = supercell_matrix self._primitive_matrix = primitive_matrix self._distance = distance self._is_diagonal = is_diagonal self._check_imaginary = check_imaginary self._cutoff_frequency = cutoff_frequency # determine imaginary freq. self._lattice_tolerance = lattice_tolerance self._pressure_target = pressure_target self._stress_tolerance = stress_tolerance self._force_tolerance = force_tolerance self._max_increase = max_increase self._max_iteration = max_iteration self._min_iteration = min_iteration self._traverse = traverse self._is_cell_relaxed = is_cell_relaxed self._stage = 0 self._tasks = [] self._energy = None self._cell = None self._phonon = None # Phonopy object self._phonon_fc3 = None # Phono3py object self._phonon_fc3_tasks = None def get_phonon(self): return self._phonon def get_phonon_fc3(self): for i, task in enumerate(self._phonon_fc3_tasks[1:]): forces_fc3.append(task.get_properties()['forces'][-1]) disp_dataset = self._phonon_fc3.get_displacement_dataset() self._phonon_fc3.produce_fc3(forces_fc3) return self._phonon_fc3 def get_cell(self): if self._is_cell_relaxed: return self._cell else: return self._phonon_fc3_tasks[0].get_cell() def get_energy(self): """Return energies at geometry optimization steps""" return self._energy def set_status(self): if self._stage == 0: task = self._tasks[0] if task.done(): status = task.get_status() if status == "done": self._status = "next" else: self._status = status else: done = True terminate = False for i, task in enumerate(self._tasks): done &= task.done() terminate |= (task.get_status() == "terminate") if done: if terminate: self._status = "terminate" else: self._status = "next" self._write_yaml() def begin(self): if not self._job: print("set_job has to be executed.") raise RuntimeError if self._is_cell_relaxed: self._phonon_fc3_tasks = [None] self._set_stage1() else: self._set_stage0() def end(self): pass def done(self): return (self._status == "terminate" or self._status == "done" or self._status == "max_iteration" or self._status == "next" or self._status == "imaginary_mode") def __next__(self): return self.next() def next(self): if self._stage == 0: if "next" in self._status: self._energy = self._tasks[0].get_energy() self._comment = "%s\\n%f" % ( self._tasks[0].get_space_group()['international'], self._energy) self._set_stage1() return self._tasks elif "terminate" in self._status and self._traverse == "restart": self._traverse = False self._set_stage0() return self._tasks else: raise StopIteration elif self._stage == 1: if "next" in self._status: disp_dataset = self._phonon_fc3.get_displacement_dataset() for disp1, task in zip(disp_dataset['first_atoms'], self._tasks): disp1['forces'] = task.get_properties()['forces'][-1] write_FORCE_SETS(disp_dataset) self._phonon.set_displacement_dataset(disp_dataset) self._phonon.produce_force_constants( calculate_full_force_constants=False) if self._exist_imaginary_mode(): self._status = "imaginary_mode" self._write_yaml() self._tasks = [] raise StopIteration else: self._set_stage2() return self._tasks elif "terminate" in self._status and self._traverse == "restart": self._reset_stage1() return self._tasks else: raise StopIteration elif self._stage == 2: if "next" in self._status: self._status = "done" forces_fc3 = [] for i, task in enumerate(self._phonon_fc3_tasks[1:]): forces_fc3.append(task.get_properties()['forces'][-1]) disp_dataset = self._phonon_fc3.get_displacement_dataset() write_FORCES_FC3(disp_dataset, forces_fc3) self._tasks = [] raise StopIteration elif "terminate" in self._status and self._traverse == "restart": self._reset_stage2() return self._tasks else: raise StopIteration else: # stage2 pass def _set_stage0(self): self._status = "equilibrium" task = self._get_equilibrium_task() self._phonon_fc3_tasks = [task] self._tasks = [task] def _set_stage1(self): self._set_phonon_fc3() if self._check_imaginary: self._stage = 1 self._status = "fc2_displacements" disp_dataset = self._phonon_fc3.get_displacement_dataset() self._tasks = self._get_displacement_tasks( stop=len(disp_dataset['first_atoms'])) self._phonon_fc3_tasks += self._tasks else: self._set_stage2() def _reset_stage1(self): self._traverse = False disp_terminated = [] for i, task in enumerate(self._tasks): if task.get_status() == "terminate": disp_terminated.append(i) disp_dataset = self._phonon_fc3.get_displacement_dataset() tasks = self._get_displacement_tasks( stop=len(disp_dataset['first_atoms'])) self._tasks = [] for i in disp_terminated: self._tasks.append(tasks[i]) self._phonon_fc3_tasks[i + 1] = tasks[i] self._status = "fc2_displacements" def _set_stage2(self): self._stage = 2 self._status = "fc3_displacements" if self._check_imaginary: disp_dataset = self._phonon_fc3.get_displacement_dataset() start_index = len(disp_dataset['first_atoms']) else: start_index = 0 self._tasks = self._get_displacement_tasks(start=start_index) self._phonon_fc3_tasks += self._tasks def _reset_stage2(self): self._traverse = False disp_terminated = [] for i, task in enumerate(self._tasks): if task.get_status() == "terminate": disp_terminated.append(i) if self._check_imaginary: disp_dataset = self._phonon_fc3.get_displacement_dataset() start_index = len(disp_dataset['first_atoms']) else: start_index = 0 tasks = self._get_displacement_tasks(start=start_index) self._tasks = [] for i in disp_terminated: self._tasks.append(tasks[i]) self._phonon_fc3_tasks[i + 1 + start_index] = tasks[i] self._status = "fc3_displacements" def _set_phonon_fc3(self): cell = self.get_cell() phonopy_cell = cell2atoms(cell) self._phonon = Phonopy(phonopy_cell, self._supercell_matrix, primitive_matrix=self._primitive_matrix, dynamical_matrix_decimals=14, force_constants_decimals=14) self._phonon_fc3 = Phono3py(phonopy_cell, self._supercell_matrix, primitive_matrix=self._primitive_matrix) self._phonon_fc3.generate_displacements(distance=self._distance, is_diagonal=self._is_diagonal) supercell = self._phonon_fc3.get_supercell() disp_dataset = self._phonon_fc3.get_displacement_dataset() self._phonon.set_displacement_dataset(disp_dataset) write_poscar(cell, "POSCAR-unitcell") write_disp_yaml(self._phonon.get_displacements(), supercell, directions=self._phonon.get_displacement_directions()) write_disp_fc3_yaml(disp_dataset, supercell) def _exist_imaginary_mode(self): if self._primitive_matrix is None: pmat = np.eye(3) else: pmat = self._primitive_matrix exact_point_matrix = np.dot(np.linalg.inv(self._supercell_matrix), pmat).T max_integer = np.rint(np.amax(np.abs(np.linalg.inv(exact_point_matrix)))) q_points = [] for i in np.arange(-max_integer, max_integer + 1): for j in np.arange(-max_integer, max_integer + 1): for k in np.arange(-max_integer, max_integer + 1): q = np.dot(exact_point_matrix, [i, j, k]) if (-1 < q).all() and (q < 1).all(): q_points.append(q) self._phonon.set_qpoints_phonon(q_points) frequencies = self._phonon.get_qpoints_phonon()[0] if (frequencies < self._cutoff_frequency).any(): self._log = "Stop at phonon calculation due to imaginary modes" return True else: return False def _write_yaml(self): w = open("%s.yaml" % self._directory, 'w') if self._lattice_tolerance is not None: w.write("lattice_tolerance: %f\n" % self._lattice_tolerance) if self._stress_tolerance is not None: w.write("stress_tolerance: %f\n" % self._stress_tolerance) w.write("pressure_target: %f\n" % self._pressure_target) w.write("force_tolerance: %f\n" % self._force_tolerance) if self._max_increase is None: w.write("max_increase: unset\n") else: w.write("max_increase: %f\n" % self._max_increase) w.write("max_iteration: %d\n" % self._max_iteration) w.write("min_iteration: %d\n" % self._min_iteration) w.write("supercell_matrix:\n") for row in self._supercell_matrix: w.write("- [ %3d, %3d, %3d ]\n" % tuple(row)) if self._primitive_matrix is not None: w.write("primitive_matrix:\n") for row in self._primitive_matrix: w.write("- [ %6.3f, %6.3f, %6.3f ]\n" % tuple(row)) w.write("distance: %f\n" % self._distance) if self._phonon_fc3_tasks[0] is not None: w.write("iteration: %d\n" % self._phonon_fc3_tasks[0].get_stage()) if self._energy: w.write("electric_total_energy: %20.10f\n" % self._energy) w.write("status: %s\n" % self._status) w.write("tasks:\n") for task in self._phonon_fc3_tasks: if task and task.get_status(): w.write("- name: %s\n" % task.get_name()) w.write(" status: %s\n" % task.get_status()) w.close()
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])
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() 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)
phonon = Phonopy(unitcell, [[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]]) force_sets = parse_FORCE_SETS() phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() q = [0.1, 0.1, 0.1] dynmat = phonon.get_dynamical_matrix_at_q(q) print(dynmat) phonon.set_qpoints_phonon(q, write_dynamical_matrices=True) print(phonon.get_qpoints_phonon()[0][0]) phonon.write_yaml_qpoints_phonon() data = yaml.load(open("qpoints.yaml")) dynmat_from_yaml = [] dynmat_data = data['phonon'][0]['dynamical_matrix'] for row in dynmat_data: vals = np.reshape(row, (-1, 2)) dynmat_from_yaml.append(vals[:, 0] + vals[:, 1] * 1j) dynmat_from_yaml = np.array(dynmat_from_yaml) print(dynmat_from_yaml) eigvals, eigvecs, = np.linalg.eigh(dynmat) frequencies = np.sqrt(np.abs(eigvals.real)) * np.sign(eigvals.real) conversion_factor_to_THz = 15.633302 print(frequencies * conversion_factor_to_THz)
import yaml import numpy as np unitcell = read_vasp("POSCAR") phonon = Phonopy(unitcell, [[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]]) force_sets = parse_FORCE_SETS() phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() q = [0.1, 0.1, 0.1] dynmat = phonon.get_dynamical_matrix_at_q(q) print(dynmat) phonon.set_qpoints_phonon(q, write_dynamical_matrices=True) print(phonon.get_qpoints_phonon()[0][0]) phonon.write_yaml_qpoints_phonon() data = yaml.load(open("qpoints.yaml")) dynmat_from_yaml = [] dynmat_data = data['phonon'][0]['dynamical_matrix'] for row in dynmat_data: vals = np.reshape(row, (-1, 2)) dynmat_from_yaml.append(vals[:, 0] + vals[:, 1] * 1j) dynmat_from_yaml = np.array(dynmat_from_yaml) print(dynmat_from_yaml) eigvals, eigvecs, = np.linalg.eigh(dynmat) frequencies = np.sqrt(np.abs(eigvals.real)) * np.sign(eigvals.real) conversion_factor_to_THz = 15.633302 print(frequencies * conversion_factor_to_THz)