Esempio n. 1
0
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}
Esempio n. 2
0
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
Esempio n. 3
0
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()
Esempio n. 4
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])
Esempio n. 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()

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)
Esempio n. 6
0
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)
Esempio n. 7
0
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)