Exemple #1
0
    def __init__(self, model=None, structure=None, atom_disp=0.015, **kwargs):
        self.model = model
        self.structure = structure
        self.atom_disp = atom_disp
        self.qpoints, self.vertices = get_qpoints_and_vertices(self.structure)
        is_plusminus = kwargs.get('is_plusminus', True)
        is_diagonal = kwargs.get('is_diagonal', True)
        is_trigonal = kwargs.get('is_diagonal', False)
        supercell_matrix = kwargs.get('is_diagonal', None)
        ph_structure = get_phonopy_structure(self.structure)
        if supercell_matrix is None:
            supercell_matrix = np.eye(3) * np.array((1, 1, 1))
        self.phonon = Phonopy(unitcell=ph_structure, supercell_matrix=supercell_matrix)
        self.phonon.generate_displacements(distance=self.atom_disp,
                                      is_plusminus=is_plusminus,
                                      is_diagonal=is_diagonal,
                                      is_trigonal=is_trigonal)

        disp_supercells = self.phonon.get_supercells_with_displacements()
        # Perfect supercell structure
        init_supercell = self.phonon.get_supercell()
        # Structure list to be returned
        self.structure_list = [get_pmg_structure(init_supercell)]

        for c in disp_supercells:
            if c is not None:
                self.structure_list.append(get_pmg_structure(c))

        forces = self.model.calculate_forces(self.structure_list)
        self.phonon.set_forces(forces[1:])
        self.phonon.produce_force_constants()
        logging.info("Force constant produced") 
Exemple #2
0
def get_f_vib_phonopy(structure, supercell_matrix, vasprun_path,
                     qpoint_mesh=(50, 50, 50), t_min=5, t_step=5, t_max=2000.0,):
    """
    Return F_vib(T) for the unitcell in eV/atom

    Parameters
    ----------
    structure : pymatgen.Structure
        Unitcell (not supercell) of interest.
    supercell_matrix : numpy.ndarray
        3x3 matrix of the supercell deformation, e.g. [[3, 0, 0], [0, 3, 0], [0, 0, 3]].
    vasprun_path : str
        String pointing to a vasprun.xml file from a force constants run
    qpoint_mesh : list
        Mesh of q-points to calculate thermal properties on.
    t_min : float
        Minimum temperature
    t_step : float
        Temperature step size
    t_max : float
        Maximum temperature (inclusive)

    Returns
    -------
    tuple
        Tuple of (temperature, F_vib, S_vib, Cv_vib, force_constants)

    """
    # get codename and version from vasprun.xml file
    code_name, code_version = get_code_version(xml=vasprun_path)
    force_constant_factor = 1.0
    if code_version[0:1] >= '6':
        force_constant_factor = 0.004091649655126895

    # get the force constants from a vasprun.xml file
    vasprun = PhonopyVasprun(vasprun_path)
    force_constants, elements = vasprun.read_force_constants()
    force_constants *= force_constant_factor

    ph_unitcell = get_phonopy_structure(structure)
    ph = Phonopy(ph_unitcell, supercell_matrix)
    # set the force constants we found
    ph.set_force_constants(force_constants)
    # calculate the thermal properties
    ph.run_mesh(qpoint_mesh)
    ph.run_thermal_properties(t_min=t_min, t_max=t_max, t_step=t_step)
    # the thermal properties are for the unit cell
    tp_dict = ph.get_thermal_properties_dict()
    temperatures = tp_dict['temperatures']
    # convert the units into our expected eV/atom-form (and per K)
    f_vib = tp_dict['free_energy'] * J_per_mol_to_eV_per_atom*1000
    s_vib = tp_dict['entropy'] * J_per_mol_to_eV_per_atom
    cv_vib = tp_dict['heat_capacity'] * J_per_mol_to_eV_per_atom
    return temperatures, f_vib, s_vib, cv_vib, ph.force_constants, code_version
Exemple #3
0
def get_phonon_dos(structure,
                   supercell_matrix,
                   force_constants,
                   qpoint_mesh=(50, 50, 50),
                   phonon_pdos=False,
                   save_data=False,
                   save_fig=False):
    '''
    Return the phonon dos

    Parameters
    ----------
    structure : pymatgen.Structure
        Unitcell (not supercell) of interest.
    supercell_matrix : numpy.ndarray
        3x3 matrix of the supercell deformation, e.g. [[3, 0, 0], [0, 3, 0], [0, 0, 3]].
    force_constants: list
        force constants
    qpoint_mesh : list
        Mesh of q-points to calculate thermal properties on.
    phonon_pdos: bool
        Determine if calculate phonon pdos or not
    save_data/save_fig: bool
        Determine if save the data/figure or not
    '''
    volume = structure.volume
    formula = structure.composition.reduced_formula
    filename = "{}-phonon-Vol{:.2f}".format(formula, volume)

    unitcell = get_phonopy_structure(structure)
    ph_dos_obj = Phonopy(unitcell, supercell_matrix)
    ph_dos_obj.set_force_constants(force_constants)

    ph_dos_obj.run_mesh(qpoint_mesh)
    ph_dos_obj.run_total_dos()
    if save_fig:
        fig_dos = ph_dos_obj.plot_total_dos()
        fig_dos.savefig(fname='{}-dos.png'.format(filename))
        fig_dos.close()
    if save_data:
        ph_dos_obj.write_total_dos(filename='{}-dos.dat'.format(filename))

    if phonon_pdos:
        ph_dos_obj.run_mesh(qpoint_mesh,
                            with_eigenvectors=True,
                            is_mesh_symmetry=False)
        ph_dos_obj.run_projected_dos()
        if save_fig:
            ph_dos_obj.plot_projected_dos().savefig(
                fname='{}-pdos.png'.format(filename))
        if save_data:
            ph_dos_obj.write_projected_dos(
                filename='{}-pdos.dat'.format(filename))
    return ph_dos_obj
Exemple #4
0
def get_phonon_band(structure,
                    supercell_matrix,
                    force_constants,
                    band_paths=None,
                    npoints=51,
                    labels=None,
                    save_data=False,
                    save_fig=False):
    '''
    Return the phonon bandstructure

    Parameters
    ----------
    structure : pymatgen.Structure
        Unitcell (not supercell) of interest.
    supercell_matrix : numpy.ndarray
        3x3 matrix of the supercell deformation, e.g. [[3, 0, 0], [0, 3, 0], [0, 0, 3]].
    force_constants: list
        force constants
    band_paths :  list, multi dimention
        Sets of end points of paths, e.g. [[[0, 0, 0], [0.5, 0.5, 0], [0.5, 0.5, 0.5]], [[0.5, 0.25, 0.75], [0, 0, 0]]]
        If it equals None, it will determine the path automatically by phononpy
    npoints: int
        Number of q-points in each path including end points.
    labels: list of str
        The label of high symmetry points, if None, it will determine it automatically by phononpy
    save_data/save_fig: bool
        Determine if save the data/figure or not
    '''
    volume = structure.volume
    formula = structure.composition.reduced_formula
    filename = "{}-phonon-Vol{:.2f}".format(formula, volume)

    unitcell = get_phonopy_structure(structure)
    ph_band_obj = Phonopy(unitcell, supercell_matrix)
    ph_band_obj.set_force_constants(force_constants)

    if band_paths:
        qpoints, connections = get_band_qpoints_and_path_connections(
            band_paths, npoints=npoints)
        ph_band_obj.run_band_structure(qpoints,
                                       path_connections=connections,
                                       labels=labels)
    else:
        ph_band_obj.auto_band_structure()
    if save_fig:
        fig_band = ph_band_obj.plot_band_structure()
        fig_band.savefig(fname='{}-band.png'.format(filename))
        fig_band.close()
    if save_data:
        ph_band_obj.write_yaml_band_structure(
            filename='{}-band.yaml'.format(filename))
    return ph_band_obj
Exemple #5
0
    def _get_phono3pyobject_phono3py(self, structure, potential,
                                     kpoint_density,
                                     displacementdistancephono3py,
                                     max_distance_third_order):
        cell = get_phonopy_structure(structure)

        kpoint = Kpoints.automatic_density(structure=structure,
                                           kppa=kpoint_density,
                                           force_gamma=True)
        mesh = kpoint.kpts[0]
        phono3py = Phono3py(cell,
                            self.smat,
                            primitive_matrix=[[1, 0., 0.], [0., 1, 0.],
                                              [0., 0., 1]],
                            mesh=mesh,
                            log_level=1)

        phono3py.generate_displacements(
            distance=displacementdistancephono3py,
            cutoff_pair_distance=max_distance_third_order)
        scells_with_disps = phono3py.get_supercells_with_displacements()

        disp_dataset = phono3py.get_displacement_dataset()
        numatoms = len(scells_with_disps[0].get_scaled_positions())
        dummy_force = np.zeros((numatoms, 3))

        set_of_forces = []
        for scell in scells_with_disps:
            if scell is not None:
                # this part is adapted from: https://web.archive.org/web/20200610084959/https://github.com/phonopy/phonopy/blob/develop/example/ase/8Si-phonon.py
                # Copyright by Atsushi Togo
                cell = Atoms(symbols=scell.get_chemical_symbols(),
                             scaled_positions=scell.get_scaled_positions(),
                             cell=scell.get_cell(),
                             pbc=True)
                cell.set_calculator(potential)
                forces = cell.get_forces()
                drift_force = forces.sum(axis=0)
                print(("[Phonopy] Drift force:" + "%11.5f" * 3) %
                      tuple(drift_force))
                for force in forces:
                    force -= drift_force / forces.shape[0]
                set_of_forces.append(forces)
            else:
                set_of_forces.append(dummy_force)
        phono3py.produce_fc3(set_of_forces,
                             displacement_dataset=disp_dataset,
                             symmetrize_fc3r=True)

        fc3 = phono3py.get_fc3()

        show_drift_fc3(fc3)
        return phono3py
Exemple #6
0
def get_f_vib_phonopy(
        structure,
        supercell_matrix,
        vasprun_path,
        qpoint_mesh=(50, 50, 50),
        t_min=5,
        t_step=5,
        t_max=2000.0,
):
    """
    Return F_vib(T) for the unitcell in eV/atom

    Parameters
    ----------
    structure : pymatgen.Structure
        Unitcell (not supercell) of interest.
    supercell_matrix : numpy.ndarray
        3x3 matrix of the supercell deformation, e.g. [[3, 0, 0], [0, 3, 0], [0, 0, 3]].
    vasprun_path : str
        String pointing to a vasprun.xml file from a force constants run
    qpoint_mesh : list
        Mesh of q-points to calculate thermal properties on.
    t_min : float
        Minimum temperature
    t_step : float
        Temperature step size
    t_max : float
        Maximum temperature (inclusive)

    Returns
    -------
    tuple
        Tuple of (temperature, F_vib, S_vib, Cv_vib, force_constants)

    """
    # get the force constants from a vasprun.xml file
    vasprun = PhonopyVasprun(vasprun_path)
    force_constants, elements = vasprun.read_force_constants()

    ph_unitcell = get_phonopy_structure(structure)
    ph = Phonopy(ph_unitcell, supercell_matrix)
    # set the force constants we found
    ph.set_force_constants(force_constants)
    # calculate the thermal properties
    ph.set_mesh(qpoint_mesh)
    ph.set_thermal_properties(t_min=t_min, t_max=t_max, t_step=t_step)
    # the thermal properties are for the unit cell
    temperatures, f_vib, s_vib, cv_vib = ph.get_thermal_properties()
    # convert the units into our expected eV/atom-form (and per K)
    f_vib *= J_per_mol_to_eV_per_atom * 1000
    s_vib *= J_per_mol_to_eV_per_atom
    cv_vib *= J_per_mol_to_eV_per_atom
    return temperatures, f_vib, s_vib, cv_vib, ph.force_constants
Exemple #7
0
    def _get_phononobject_phonopy(self,
                                  structure,
                                  potential,
                                  smat,
                                  save_parameters,
                                  path,
                                  displacement_distance=0.01):
        cell = get_phonopy_structure(structure)
        phonon = Phonopy(cell,
                         smat,
                         primitive_matrix=[[1.0, 0.0, 0.0], [0.0, 1, 0.0],
                                           [0., 0., 1.0]],
                         factor=VaspToTHz)

        # displacements
        phonon.generate_displacements(distance=displacement_distance)
        print("[Phonopy] Atomic displacements:")
        disps = phonon.get_displacements()
        for d in disps:
            print("[Phonopy] %d %s" % (d[0], d[1:]))

        supercells = phonon.get_supercells_with_displacements()
        # Force calculations by calculator
        set_of_forces = []
        for scell in supercells:
            cell = Atoms(symbols=scell.get_chemical_symbols(),
                         scaled_positions=scell.get_scaled_positions(),
                         cell=scell.get_cell(),
                         pbc=True)
            cell.set_calculator(potential)
            # this part is adapted from: https://web.archive.org/web/20200610084959/https://github.com/phonopy/phonopy/blob/develop/example/ase/8Si-phonon.py
            # Copyright by Atsushi Togo
            forces = cell.get_forces()
            drift_force = forces.sum(axis=0)
            print(
                ("[Phonopy] Drift force:" + "%11.5f" * 3) % tuple(drift_force))
            for force in forces:
                force -= drift_force / forces.shape[0]
            set_of_forces.append(forces)

        phonon.produce_force_constants(forces=set_of_forces)
        if save_parameters:
            phonon.save(path)
        return phonon
Exemple #8
0
    def test_structure_conversion(self):
        s_pmg = PymatgenTest.get_structure("LiFePO4")
        s_ph = get_phonopy_structure(s_pmg)
        s_pmg2 = get_pmg_structure(s_ph)

        coords_ph = s_ph.get_scaled_positions()
        symbols_pmg = {e.symbol for e in s_pmg.composition.keys()}
        symbols_pmg2 = {e.symbol for e in s_pmg2.composition.keys()}

        self.assertAlmostEqual(s_ph.get_cell()[1, 1],
                               s_pmg.lattice._matrix[1, 1], 7)
        self.assertAlmostEqual(s_pmg.lattice._matrix[1, 1],
                               s_pmg2.lattice._matrix[1, 1], 7)
        self.assertEqual(symbols_pmg, set(s_ph.symbols))
        self.assertEqual(symbols_pmg, symbols_pmg2)
        self.assertArrayAlmostEqual(coords_ph[3], s_pmg.frac_coords[3])
        self.assertArrayAlmostEqual(s_pmg.frac_coords[3],
                                    s_pmg2.frac_coords[3])
        self.assertEqual(s_ph.get_number_of_atoms(), s_pmg.num_sites)
        self.assertEqual(s_pmg.num_sites, s_pmg2.num_sites)
Exemple #9
0
    def runSimulation(self):
        starting_struct = singleFromFile(self.args)
        relaxed_struct = runCalc("all_relax", ["structures"],
                                 [starting_struct], self.args)["structures"][0]

        phonopy_struct = get_phonopy_structure(relaxed_struct)

        supercell_matrix = 3 * eye(3)
        phonon = Phonopy(phonopy_struct, supercell_matrix)
        phonon.generate_displacements(distance=0.01)
        supercells = phonon.supercells_with_displacements
        phonon_structs = [get_pmg_structure(struct) for struct in supercells]

        forces = runCalc("all_static", ["forces"], phonon_structs,
                         self.args)["forces"]

        phonon.set_forces(array(forces))
        phonon.produce_force_constants()
        phonon.symmetrize_force_constants()

        self.plotter = PhononBSPlotter(
            get_phonon_band_structure_symm_line_from_fc(
                relaxed_struct, supercell_matrix, phonon.force_constants))
    def get_phonon(self, phonon, **kwargs):
        flag_savefig = kwargs.get('savefig', False)
        flag_savedata = kwargs.get('savedata', False)
        flag_band = kwargs.get('band', False)
        flag_dos = kwargs.get('phonon_dos', False)
        flag_pdos = kwargs.get('phonon_pdos', False)

        mesh = kwargs.get('mesh', [50, 50, 50])
        labels = kwargs.get('labels', None)

        if 'unitcell' not in phonon:
            raise FileNotFoundError(
                'There is no phonon result. Please run phonon first.')
        self.head = ['Temperature', 'F_vib', 'CV_vib', 'S_vib']
        self.unit = ['K', 'eV', 'eV/K', 'eV/K']
        self.data = np.vstack((phonon.pop('temperatures'), phonon.pop('F_vib'),
                               phonon.pop('CV_vib'), phonon.pop('S_vib'))).T
        filename = '{}-phonon-Vol{:.2f}'.format(self.formula, self.volume)

        unitcell = get_phonopy_structure(self.structure)
        supercell_matrix = phonon['supercell_matrix']
        force_constants = phonon['force_constants']
        ph = Phonopy(unitcell, supercell_matrix)
        ph.set_force_constants(force_constants)

        #for band structure
        if flag_band:
            if 'path' in kwargs:
                qpoints, connections = get_band_qpoints_and_path_connections(
                    path, npoints=51)
                ph.run_band_structure(qpoints,
                                      path_connections=connections,
                                      labels=labels)
            else:
                ph.auto_band_structure()
            if flag_savefig:
                fig_band = ph.plot_band_structure()
                fig_band.savefig(fname='{}-band.png'.format(filename))
                fig_band.close()
            if flag_savedata:
                ph.write_yaml_band_structure(
                    filename='{}-band.yaml'.format(filename))

        #for dos
        if flag_dos:
            ph.run_mesh(mesh)
            ph.run_total_dos()
            #phonon_dos_tmp = np.vstack((ph._total_dos._frequency_points, ph._total_dos._dos))
            #print(phonon_dos_tmp)
            #print(type(phonon_dos_tmp))
            if flag_savefig:
                fig_dos = ph.plot_total_dos()
                fig_dos.savefig(fname='{}-dos.png'.format(filename))
                fig_dos.close()
            if flag_savedata:
                ph.write_total_dos(filename='{}-dos.dat'.format(filename))
        #for pdos.
        if flag_pdos:
            ph.run_mesh(mesh, with_eigenvectors=True, is_mesh_symmetry=False)
            ph.run_projected_dos()
            if flag_savefig:
                ph.plot_projected_dos().savefig(
                    fname='{}-pdos.png'.format(filename))
            if flag_savedata:
                ph.write_projected_dos(filename='{}-pdos.dat'.format(filename))

        phonon.pop('_id')
        self.parameter = phonon
Exemple #11
0
def load_phonopy(filename, structure, dim, symprec=0.01, primitive_matrix=None,
                 factor=VaspToTHz, symmetrise=True, born=None, write_fc=False):
    """Load phonopy output and return an ``phonopy.Phonopy`` object.

    Args:
        filename (str): Path to phonopy output. Can be any of ``FORCE_SETS``,
            ``FORCE_CONSTANTS``, or ``force_constants.hdf5``.
        structure (:obj:`~pymatgen.core.structure.Structure`): The unitcell
            structure.
        dim (list): The supercell size, as a :obj:`list` of :obj:`float`.
        symprec (:obj:`float`, optional): The tolerance for determining the
            crystal symmetry.
        primitive_matrix (:obj:`list` or :obj:`str`, optional): The
            transformation matrix from the conventional to primitive cell. Only
            required when the conventional cell was used as the starting
            structure. Should be provided as a 3x3 :obj:`list` of :obj:`float`.
            Alternatively the str 'auto' may be provided.
        factor (:obj:`float`, optional): The conversion factor for phonon
            frequency. Defaults to :obj:`phonopy.units.VaspToTHz`.
        symmetrise (:obj:`bool`, optional): Symmetrise the force constants.
            Defaults to ``True``.
        born (:obj:`str`, optional): Path to file containing Born effective
            charges. Should be in the same format as the file produced by the
            ``phonopy-vasp-born`` script provided by phonopy.
        write_fc (:obj:`bool` or :obj:`str`,  optional): Write the force
            constants to disk. If ``True``, a ``FORCE_CONSTANTS`` file will be
            written. Alternatively, if set to ``"hdf5"``, a
            ``force_constants.hdf5`` file will be written. Defaults to
            ``False`` (force constants not written).
    """
    unitcell = get_phonopy_structure(structure)
    num_atom = unitcell.get_number_of_atoms()
    num_satom = determinant(dim) * num_atom

    phonon = Phonopy(unitcell, dim, primitive_matrix=primitive_matrix,
                     factor=factor, symprec=symprec)

    if 'FORCE_CONSTANTS' == filename or '.hdf5' in filename:
        # if force constants exist, use these to avoid recalculating them
        if '.hdf5' in filename:
            fc = file_IO.read_force_constants_hdf5(filename)

        elif 'FORCE_CONSTANTS' == filename:
            fc = file_IO.parse_FORCE_CONSTANTS(filename=filename)

        if fc.shape[0] != num_satom:
            msg = ("\nNumber of atoms in supercell is not consistent with the "
                   "matrix shape of\nforce constants read from {}.\nPlease"
                   "carefully check --dim.")
            logging.error(msg.format(filename))
            sys.exit()

        phonon.set_force_constants(fc)

    elif 'FORCE_SETS' == filename:
        # load the force sets from file and calculate force constants
        fs = file_IO.parse_FORCE_SETS()

        if fs['natom'] != num_satom:
            msg = ("\nNumber of atoms in supercell is not consistent with the "
                   "the data in FORCE_SETS\nPlease carefully check --dim.")
            logging.error(msg.format(filename))
            sys.exit()

        phonon.set_displacement_dataset(fs)

        logging.info("Calculating force constants...")
        phonon.produce_force_constants()

    if born:
        # load born parameters from a file
        nac_params = file_IO.parse_BORN(phonon._primitive,
                                        symprec=symprec,
                                        filename=born)

        # set the nac unit conversion factor manual,  specific to VASP
        nac_params['factor'] = Hartree * Bohr
        phonon.set_nac_params(nac_params)

    if symmetrise:
        phonon.symmetrize_force_constants()

    if write_fc == 'hdf5':
        file_IO.write_force_constants_to_hdf5(phonon.get_force_constants())
        logging.info("Force constants written to force_constants.hdf5.")

    elif write_fc:
        file_IO.write_FORCE_CONSTANTS(phonon.get_force_constants())
        logging.info("Force constants written to FORCE_CONSTANTS.")

    return phonon
Exemple #12
0
    def MVibrationauto(self, maxx=4500):
        import os
        import numpy as np
        from pymatgen.io.phonopy import get_phonopy_structure
        import pymatgen as pmg
        from pymatgen.io.vasp.outputs import Vasprun
        from pymatgen.io.vasp import Poscar
        from pymatgen.symmetry.kpath import KPathSeek, KPathBase
        from phonopy.phonon.band_structure import get_band_qpoints_and_path_connections
        from phonopy import Phonopy
        from phonopy.structure.atoms import Atoms as PhonopyAtoms
        from pymatgen.phonon.plotter import PhononBSPlotter
        from pymatgen.phonon.bandstructure import PhononBandStructureSymmLine
        import csv
        import pandas as pd
        import matplotlib.pyplot as plt

        os.chdir(self.dire)
        print(os.getcwd())

        poscar = Poscar.from_file("POSCAR")
        structure = poscar.structure
        scell = [[2, 0, 0], [0, 2, 0], [0, 0, 2]]
        vrun = Vasprun("vasprun.xml")
        phonopyAtoms = get_phonopy_structure(structure)
        phonon = Phonopy(phonopyAtoms, scell)

        phonon.set_force_constants(-vrun.force_constants)

        # labels = ["$\\Gamma$", "X", "U", "K", "L"]
        labels = ['K', "$\\Gamma$", 'L', 'W', 'X']
        # bands = []
        cd = KPathSeek(structure)
        cds = cd.kpath
        # print(cds)
        for k, v in cds.items():
            if "kpoints" in k:

                dics = v
            else:
                dicss = v
        print(dics)
        print(dicss)

        # bands=[]
        # for k,v in dics.items():
        #     if k in dicss[0]:
        #         bands.append(v)

        path = []
        #

        # bandd1=[]
        # for k,v in dics.items():
        #     for i in dicss[0]:
        #             if k in i:
        #                 bandd1.append(v)
        # path.append(bandd1)

        bandd1 = []
        for i in dicss[1]:
            for k, v in dics.items():
                if k in i:
                    bandd1.append(v)
        path.append(bandd1)
        print(dicss[1])
        qpoints, connections = get_band_qpoints_and_path_connections(
            path, npoints=51)
        phonon.run_band_structure(qpoints,
                                  path_connections=connections,
                                  labels=labels)

        print(path)

        # kpoints=cd.get_kpoints

        # print(kpoints)

        # phonon.set_band_structure(bands,labels=labels)

        phonon.plot_band_structure().show()
        phonon.plot_band_structure().savefig("BAND.png",
                                             bbox_inches='tight',
                                             transparent=True,
                                             dpi=300,
                                             format='png')
        # phonon.write_band_structure()
        mesh = [31, 31, 31]
        phonon.set_mesh(mesh)

        phonon.set_total_DOS()
        phonon.write_total_DOS()
        phonon.plot_total_DOS().show()
        phonon.plot_total_DOS().savefig("DOS.png")
        # c = np.fromfile('total_dos.dat', dtype=float)

        datContent = [
            i.strip().split() for i in open("./total_dos.dat").readlines()
        ]
        del datContent[0]
        x_ax = []
        y_ax = []
        for i in datContent:
            x_ax.append(1 / ((3 * (10**8) / (float(i[0]) * (10**12))) * 100))
            y_ax.append(float(i[1]))

        da = {'Density of states': x_ax, 'Frequency': y_ax}
        df = pd.DataFrame(da)  #构造原始数据文件
        df.to_excel("Wave number.xlsx")  #生成Excel文件,并存到指定文件路径下

        fig, ax = plt.subplots()

        line1 = ax.plot(x_ax, y_ax, c='grey')
        ax.set_xlim([maxx, 0])

        # 以下是XRD图片的格式设置
        #设置横纵坐标的名称以及对应字体格式
        font2 = {
            'family': 'Times New Roman',
            'weight': 'bold',
        }
        plt.xlabel('Wavenumber ($\mathregular{cm^-}$$\mathregular{^1}$)',
                   font2)
        plt.ylabel('Density of states', font2)

        #不显示Y轴的刻度
        plt.yticks([])

        #设置图例对应格式和字体
        font1 = {
            'family': 'Times New Roman',
            'weight': 'bold',
        }
        # ax.legend(edgecolor='none', prop=font1)

        # plt.legend(edgecolor='none', prop=font1)
        # plt.set_facecolor('none')
        ax.set_facecolor('none')

        #存储为
        fig.savefig('FTIR.png',
                    bbox_inches='tight',
                    transparent=True,
                    dpi=300,
                    format='png')  #指定分辨率,边界紧,背景透明
        plt.show()
Exemple #13
0
    def Vibration(self, maxx=4500):
        import os
        import numpy as np
        from pymatgen.io.phonopy import get_phonopy_structure
        import pymatgen as pmg
        from pymatgen.io.vasp.outputs import Vasprun
        from pymatgen.io.vasp import Poscar
        from pymatgen.symmetry.kpath import KPathSeek, KPathBase

        from phonopy import Phonopy
        from phonopy.structure.atoms import Atoms as PhonopyAtoms
        from pymatgen.phonon.plotter import PhononBSPlotter
        from pymatgen.phonon.bandstructure import PhononBandStructureSymmLine
        import csv
        import pandas as pd
        import matplotlib.pyplot as plt

        os.chdir(self.dire)
        print(os.getcwd())

        poscar = Poscar.from_file("POSCAR")
        structure = poscar.structure
        scell = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
        vrun = Vasprun("vasprun.xml")
        phonopyAtoms = get_phonopy_structure(structure)
        phonon = Phonopy(phonopyAtoms, scell)

        phonon.set_force_constants(-vrun.force_constants)

        labels = ["$\\Gamma$", "X", "U", "K", "$\\Gamma$", "L", "W"]
        bands = []

        # path 1
        q_start = np.array([0.0, 0.0, 0.0])
        q_end = np.array([0.5, 0.0, 0.0])
        band = []
        for i in range(51):
            band.append(q_start + (q_end - q_start) / 50 * i)
        bands.append(band)

        # path 2
        q_start = np.array([0.5, 0.0, 0.0])
        q_end = np.array([0.5, 0.5, 0.0])
        band = []
        for i in range(51):
            band.append(q_start + (q_end - q_start) / 50 * i)
        bands.append(band)

        # # path 3
        # q_start  = np.array([0.5, 0.5, 0.0])
        # q_end    = np.array([-0.0, -0.0, 0.0])
        # band = []
        # for i in range(51):
        #     band.append(q_start + (q_end - q_start) / 50 * i)
        # bands.append(band)

        # # path 4
        # q_start  = np.array([0.0, 0.0, 0.0])
        # q_end    = np.array([0.5, 0.5, 0.5])
        # band = []
        # for i in range(51):
        #     band.append(q_start + (q_end - q_start) / 50 * i)
        # bands.append(band)

        print(bands)

        phonon.set_band_structure(bands)

        phonon.plot_band_structure().show()
        phonon.plot_band_structure().savefig("BAND.png")
        mesh = [31, 31, 31]
        phonon.set_mesh(mesh)

        phonon.set_total_DOS()
        phonon.write_total_DOS()
        phonon.plot_total_DOS().show()
        phonon.plot_total_DOS().savefig("DOS.png")
        # c = np.fromfile('total_dos.dat', dtype=float)

        datContent = [
            i.strip().split() for i in open("./total_dos.dat").readlines()
        ]
        del datContent[0]
        x_ax = []
        y_ax = []
        for i in datContent:
            x_ax.append(1 / ((3 * (10**8) / (float(i[0]) * (10**12))) * 100))
            y_ax.append(float(i[1]))

        da = {'Density of states': x_ax, 'Frequency': y_ax}
        df = pd.DataFrame(da)  #构造原始数据文件
        df.to_excel("Wave number.xlsx")  #生成Excel文件,并存到指定文件路径下

        fig, ax = plt.subplots()

        line1 = ax.plot(x_ax, y_ax, c="grey")
        ax.set_xlim([maxx, 0])

        # 以下是XRD图片的格式设置
        #设置横纵坐标的名称以及对应字体格式
        font2 = {
            'family': 'Times New Roman',
            'weight': 'bold',
        }
        plt.xlabel('Wavenumber ($\mathregular{cm^-}$$\mathregular{^1}$)',
                   font2)
        plt.ylabel('Density of states', font2)

        #不显示Y轴的刻度
        plt.yticks([])

        #设置图例对应格式和字体
        font1 = {
            'family': 'Times New Roman',
            'weight': 'bold',
        }
        # ax.legend(edgecolor='none', prop=font1)

        # plt.legend(edgecolor='none', prop=font1)
        # plt.set_facecolor('none')
        ax.set_facecolor('none')

        #存储为
        fig.savefig('FTIR.png',
                    bbox_inches='tight',
                    transparent=True,
                    dpi=300,
                    format='png')  #指定分辨率,边界紧,背景透明
        plt.show()
Exemple #14
0
def abinit_to_phonopy(anaddbnc,
                      supercell_matrix,
                      symmetrize_tensors=False,
                      output_dir_path=None,
                      prefix_outfiles="",
                      symprec=1e-5,
                      set_masses=False):
    """
    Converts the interatomic force constants(IFC), born effective charges(BEC) and dielectric
    tensor obtained from anaddb to the phonopy format. Optionally writes the
    standard phonopy files to a selected directory: FORCE_CONSTANTS, BORN (if BECs are available)
    POSCAR of the unit cell, POSCAR of the supercell.

    The conversion is performed taking the IFC in the Wigner–Seitz supercell with weights
    as produced by anaddb and reorganizes them in a standard supercell multiple of the
    unit cell. Operations are vectorized using numpy. This may lead to the allocation of
    large arrays in case of very large supercells.

    Performs a check to verify if the two codes identify the same symmetries and it gives a
    warning in case of failure. Mismatching symmetries may lead to incorrect conversions.

    Args:
        anaddbnc: an instance of AnaddbNcFile. Should contain the output of the IFC analysis,
            the BEC and the dielectric tensor.
        supercell_matrix: the supercell matrix used for phonopy. Any choice is acceptable, however
            the best agreement between the abinit and phonopy results is obtained if this is set to
            a diagonal matrix with on the diagonal the ngqpt used to generate the anaddb.nc.
        symmetrize_tensors: if True the tensors will be symmetrized in the Phonopy object and
            in the output files. This will apply to IFC, BEC and dielectric tensor.
        output_dir_path: a path to a directory where the phonopy files will be created
        prefix_outfiles: a string that will be added as a prefix to the name of the written files
        symprec: distance tolerance in Cartesian coordinates to find crystal symmetry in phonopy.
            It might be that the value should be tuned so that it leads to the the same symmetries
            as in the abinit calculation.
        set_masses: if True the atomic masses used by abinit will be added to the PhonopyAtoms
            and will be present in the returned Phonopy object. This should improve compatibility
            among abinit and phonopy results if frequencies needs to be calculated.

    Returns:
        An instance of a Phonopy object that contains the IFC, BEC and dieletric tensor data.
    """

    ifc = anaddbnc.ifc
    nac_params = None
    becs = None
    epsinf = None
    if anaddbnc.becs is not None and anaddbnc.epsinf is not None:
        becs = anaddbnc.becs.values
        epsinf = anaddbnc.epsinf

        # according to the phonopy website 14.399652 is not the coefficient for abinit
        # probably it relies on the other conventions in the output.
        nac_params = {"born": becs, "dielectric": epsinf, "factor": 14.399652}

    s = anaddbnc.structure

    phon_at = get_phonopy_structure(s)
    if set_masses:
        phon_at.masses = [anaddbnc.amu[n] for n in phon_at.numbers]

    # use phonopy to get the proper supercell given by the primitive and the matrix
    # and convert it to pymatgen
    phonon = Phonopy(phon_at,
                     supercell_matrix,
                     primitive_matrix=np.eye(3),
                     nac_params=nac_params,
                     symprec=symprec)
    phon_supercell = phonon.get_supercell()
    supercell = get_pmg_structure(phon_supercell)

    abi_hall_num = s.abi_spacegroup.get_spglib_hall_number()
    spglib_hall_num = phonon.symmetry.dataset["hall_number"]
    if abi_hall_num != spglib_hall_num:
        warnings.warn(
            "The hall number obtained based on the DDB symmetries differs "
            f"from the one calculated with spglib: {abi_hall_num} versus "
            f"{spglib_hall_num}. The conversion may be incorrect. Try changing symprec."
        )

    # convert to phonopy units
    at_cart = ifc.atoms_cart_coord * abu.Bohr_Ang
    ifccc = ifc.ifc_cart_coord * abu.Ha_eV / abu.Bohr_Ang**2
    weights = ifc.ifc_weights
    latt = supercell.lattice

    ifcph = np.zeros((len(s), len(supercell), 3, 3))

    # loop over the atoms in the primitive cell
    # other operations are vectorized using numpy arrays. Some array may require large allocations
    for i, (site, c_list, w_list) in enumerate(zip(s, at_cart, weights)):

        ind_w = np.where(w_list > 0)
        ifccc_loc = ifccc[i, ind_w[0]]

        w_list = w_list[ind_w]
        c_list = c_list[ind_w]

        # align the coordinates of the first atom in the list (the site under consideration)
        # with the site in the primitive cell.
        c_list = c_list - c_list[0] + site.coords

        # convert to fractional coordinates as needed by the Lattice to get the distances
        f_list = latt.get_fractional_coords(c_list)
        sc_fcoords = supercell.frac_coords

        # construct the list of sites of the supercell that are closer to sites in
        # the primitive cell
        dist_and_img = [
            latt.get_distance_and_image(f_list[0], fc) for fc in sc_fcoords
        ]
        # the function gives the translation of the image, but it should be applied to the coordinates.
        # Only the positions are needed
        nearest_sc_fcoords = [
            fc + trasl for (_, trasl), fc in zip(dist_and_img, sc_fcoords)
        ]

        # divide by the corresponding weights. Elements with weights 0 were discarded above
        ifccc_loc = np.transpose(ifccc_loc, (0, 2, 1)) / w_list[:, None, None]

        # create an array with all the possible pairs
        # instantiating this array seems slow but seems still faster than the required loops
        coord_pairs = np.array(
            list(itertools.product(nearest_sc_fcoords, f_list)))

        # find the pairs that match between the coordinates of the modified supercell and the f_list
        ind_match = np.where(
            np.abs(coord_pairs[:, 0] -
                   coord_pairs[:, 1]).sum(axis=1) < 1e-6)[0]
        # set the ifc for phonopy in the final array corresponding to the matching indices.
        n_points_f_list = len(f_list)
        ifcph[i, ind_match // n_points_f_list] = ifccc_loc[ind_match %
                                                           n_points_f_list]

    phonon.set_force_constants(ifcph)
    if symmetrize_tensors:
        phonon.symmetrize_force_constants()

    if output_dir_path:
        makedirs_p(output_dir_path)

        fc_filepath = os.path.join(output_dir_path,
                                   prefix_outfiles + "FORCE_CONSTANTS")
        write_FORCE_CONSTANTS(phonon.get_force_constants(), fc_filepath)

        if becs is not None and epsinf is not None:
            born_filepath = os.path.join(output_dir_path,
                                         prefix_outfiles + "BORN")
            write_BORN(phon_at,
                       borns=becs,
                       epsilon=epsinf,
                       filename=born_filepath,
                       symmetrize_tensors=symmetrize_tensors)

        poscar_filepath = os.path.join(output_dir_path,
                                       prefix_outfiles + "POSCAR")
        poscar = Poscar(s)
        poscar.write_file(poscar_filepath, significant_figures=15)

        supercell_filepath = os.path.join(output_dir_path,
                                          prefix_outfiles + "supercell_POSCAR")
        superce_poscar = Poscar(supercell)
        superce_poscar.write_file(supercell_filepath, significant_figures=15)

    return phonon
Exemple #15
0
def phonopy_to_abinit(unit_cell,
                      supercell_matrix,
                      out_ddb_path,
                      ngqpt=None,
                      qpt_list=None,
                      force_constants=None,
                      force_sets=None,
                      born=None,
                      primitive_matrix="auto",
                      symprec=1e-5,
                      tolsym=None,
                      supercell=None,
                      calculator=None,
                      manager=None,
                      workdir=None,
                      pseudos=None,
                      verbose=False):
    """
    Converts the data from phonopy to an abinit DDB file. The data can be provided
    in form of arrays or paths to the phonopy files that should be parsed.
    The minimal input should contains the FORCE_CONSTANTS or FORCE_SETS.
    If BORN is present the Born effective charges (BEC) and dielectric
    tensor will also be added to the DDB.

    The best agreement is obtained with supercell_matrix and ngqpt being
    equivalent (i.e. supercell_matrix a diagonal matrix with ngqpt as diagonal
    elements). Non diagonal supercell_matrix are allowed as well, but the information
    encoded in the DDB will be the result of an interpolation done through phonopy.

    Phonopy is used to convert the IFC to the dynamical matrix. However, in order to
    determine the list of q-points in the irreducible Brillouin zone and to prepare the
    base for the final DDB file, abinit will be called for a very short and inexpensive run.

    Performs a check to verify if the two codes identify the same symmetries and it gives a
    warning in case of failure. Mismatching symmetries may lead to incorrect conversions.

    Args:
        unit_cell: a |Structure| object that identifies the unit cell used for the phonopy
            calculation.
        supercell_matrix: a 3x3 array representing the supercell matrix used to generated the
            forces with phonopy.
        out_ddb_path: a full path to the file where the new DDB will be written
        ngqpt: a list of 3 elements indicating the grid of q points that will be used in the DDB.
        qpt_list: alternatively to ngqpt an explicit list of q-points can be provided here.
            At least one among ngqpt and qpt_list should be defined.
        force_constants: an array with shape (num atoms unit cell, num atoms supercell, 3, 3)
            containing the force constants. Alternatively a string with the path to the
            FORCE_CONSTANTS file. This or force_set should be defined. If both given this
            has precedence.
        force_sets: a dictionary obtained from the force sets generated with phonopy.
            Alternatively a string with the path to the FORCE_SETS file. This or force_constants
            should be defined.
        born: a dictionary with "dielectric" and "born" keywords as obtained from the nac_params
            in phonopy. Alternatively a string with the path to the BORN file. Notice that
            the "factor" attribute is not taken into account, so the values should be in
            default phonopy units.
        primitive_matrix: a 3x3 array with the primitive matrix passed to Phonopy. "auto" will
            use spglib to try to determine it automatically. If the DDB file should contain the
            actual unit cell this should be the identity matrix.
        symprec: distance tolerance in Cartesian coordinates to find crystal symmetry in phonopy.
            It might be that the value should be tuned so that it leads to the the same symmetries
            as in the abinit calculation.
        tolsym: Gives the tolerance to identify symmetries in abinit. See abinit documentation for
            more details.
        supercell: if given it should represent the supercell used to get the force constants,
            without any perturbation. It will be used to match it to the phonopy supercell
            and sort the IFC in the correct order.
        calculator: a string with the name of the calculator. Will be used to set the conversion
            factor for the force constants coming from phonopy.
        manager: |TaskManager| object. If None, the object is initialized from the configuration file
        pseudos: List of filenames or list of |Pseudo| objects or |PseudoTable| object. It will be
            used by abinit to generate the base DDB file. If None the abipy.data.hgh_pseudos.HGH_TABLE
            table will be used.
        verbose: verbosity level. Set it to a value > 0 to get more information
        workdir: path to the directory where the abinit calculation will be executed.

    Returns:
        a DdbFile instance of the file written in out_ddb_path.
    """

    if ngqpt is None and qpt_list is None:
        raise ValueError(
            "at least one among nqgpt and qpt_list should be defined")

    if force_sets is None and force_constants is None:
        raise ValueError(
            "at least one of force_sets and force_constants should be provided"
        )

    phon_at = get_phonopy_structure(unit_cell)

    if isinstance(force_constants, str):
        force_constants = parse_FORCE_CONSTANTS(filename=force_constants)
    elif force_constants is not None:
        force_constants = np.array(force_constants)
        force_sets = None

    if isinstance(force_sets, str):
        force_sets = parse_FORCE_SETS(filename=force_sets)

    # no nac_params here, otherwise they will be used for the interpolation
    phonon = Phonopy(phon_at,
                     supercell_matrix,
                     primitive_matrix=primitive_matrix,
                     nac_params=None,
                     symprec=symprec,
                     calculator=calculator)

    primitive = get_pmg_structure(phonon.primitive)

    if isinstance(born, str):
        born = parse_BORN(phonon.primitive, filename=born)

    if supercell is not None:
        ph_supercell = get_pmg_structure(phonon.supercell)
        if not np.allclose(supercell.lattice.matrix,
                           ph_supercell.lattice.matrix):
            raise RuntimeError("The lattice of the supercells do not match")
        sc_mapping = []
        for i, site_orig in enumerate(supercell):
            for j, site_ph in enumerate(ph_supercell):
                d = supercell.lattice.get_distance_and_image(
                    site_orig.frac_coords, site_ph.frac_coords)[0]
                if d < 1e-5:
                    sc_mapping.append(j)
                    break
            else:
                raise RuntimeError(
                    f"Could not find a match for site {i} with coords "
                    f"{site_orig.cart_coords} in the supercell.")

        # cross check that the same atom was not matched twice
        n_matches = len(set(sc_mapping))
        if n_matches < len(supercell):
            raise RuntimeError(
                f"Found matches for {n_matches} different atoms in the supercell: {sc_mapping}"
            )

        force_constants = force_constants[:, sc_mapping]

    if force_constants is not None:
        phonon.set_force_constants(force_constants)
    else:
        phonon.dataset = force_sets
        phonon.produce_force_constants()

    if calculator:
        units = get_default_physical_units(calculator)
        fc_factor = get_force_constant_conversion_factor(
            units["force_constants_unit"], None)
        phonon.set_force_constants(phonon.force_constants * fc_factor)

    if pseudos is None:
        from abipy.data.hgh_pseudos import HGH_TABLE
        pseudos = HGH_TABLE

    inp = minimal_scf_input(primitive, pseudos)

    # get the qpoints list if not defined
    if qpt_list is None:
        inp["ngkpt"] = ngqpt
        qpt_list = inp.abiget_ibz(verbose=verbose)[0]

    dm_list = get_dm(phonon, qpt_list, primitive)

    if born is not None:
        # for the conversion of the BEC the zion (i.e. the ionic charge of the pseudo)
        # it is an additive factor and should be the same that goes in the header of the DDB,
        # so take it from the pseudos used to generate it.
        zion = inp.valence_electrons_per_atom
        born_data = generate_born_deriv(born, zion, primitive)
    else:
        born_data = None

    inp = minimal_scf_input(primitive, pseudos)
    if tolsym is not None:
        inp["tolsym"] = tolsym
    task = inp.run_in_shell(workdir=workdir, manager=manager, verbose=verbose)

    # use the output of abinit to check that the spacegroup identified by
    # phonopy and abinit are the same.
    with GsrFile(task.opath_from_ext("GSR.nc")) as gsr:
        abi_spg = gsr.structure.abi_spacegroup.spgid
    spglib_spg = phonon.symmetry.dataset["number"]
    if abi_spg != spglib_spg:
        warnings.warn(
            "The space group number obtained based on the DDB symmetries differs "
            f"from the one calculated with spglib: {abi_spg} versus "
            f"{spglib_spg}. The convertion may be incorrect. Try changing symprec or tolsym."
        )

    tmp_ddb_path = task.opath_from_ext("DDB")

    ddb = DdbFile(tmp_ddb_path)
    # remove the blocks generated by the calculation and that are meaningless
    ddb.remove_block(dord=0)
    ddb.remove_block(dord=1)

    add_data_ddb(ddb, dm_list, qpt_list, born_data)

    ddb.write(out_ddb_path)

    new_ddb = DdbFile(out_ddb_path)
    return new_ddb