Ejemplo n.º 1
0
def phonopy_dos(filename, poscar='POSCAR', atoms=None):
    """Loads phonopy DoS and collates data per atom and as a total.

    By default reads atom names from a POSCAR, but can be overridden to
    allow for separation of environments.

    Arguments
    ---------

        filename : str
            path to phonopy projected_dos.dat or similar.
        poscar : str, optional
            path to POSCAR. Ignored if atoms specified. Default: POSCAR.
        atoms : str or array-like, optional
            atoms in POSCAR order. Atom names can be repeated, in which
            case their contributions are summed. Numbers can indicate
            repetition in the manner of a chemical formula, so the
            following are all acceptable and equivalent: "Ba 1 Sn 2 O 3",
            "Ba Sn Sn O O O", "Ba Sn O 3". Different environments can be
            distinguised with different atom names.
            Default: read from POSCAR.

    Returns
    -------

        dict
            frequency, DoS per atom and total.
    """

    # load data

    data = np.transpose(np.loadtxt(filename))
    units = tp.settings.units()
    data2 = {
        'frequency': data[0],
        'meta': {
            'phonon_dos_source': 'phonopy',
            'units': {
                'frequency': units['frequency']
            }
        }
    }

    conversions = settings.phonopy_conversions()
    if 'frequency' in conversions:
        data2['frequency'] *= conversions['frequency']

    if atoms is None:
        from pymatgen.io.vasp.inputs import Poscar
        poscar = Poscar.from_file(poscar,
                                  check_for_POTCAR=False,
                                  read_velocities=False).as_dict()
        atoms = [p['label'] for p in poscar['structure']['sites']]
    elif isinstance(atoms, str):
        atoms = atoms.split()

    # combine atoms contributions

    i = 0
    n = 1
    while i < len(atoms):
        try:
            atoms[i + 1] = int(atoms[i + 1])
            if atoms[i] in data2:
                data2[atoms[i]] += np.sum(data[n:n + atoms[i + 1]], axis=0)
            else:
                data2[atoms[i]] = np.sum(data[n:n + atoms[i + 1]], axis=0)
            n += atoms[i + 1]
            i += 2
        except Exception:
            if atoms[i] in data2:
                data2[atoms[i]] += data[n]
            else:
                data2[atoms[i]] = data[n]
            n += 1
            i += 1

    data2['total'] = np.sum(data[1:], axis=0)

    return data2
Ejemplo n.º 2
0
def phonopy_dispersion(filename, xdata=None):
    """Loads phonopy dispersion, and can scale the x values.

    Scaling the x values is necessary to plot multiple dispersions on
    the same axes.

    Arguments
    ---------

        filename : str
            filepath.

        xdata : dict, optional
            data for the dispersion to scale this to. Should have the
            same path, must have the same number of labels. Not
            necessary if using tp.plot.phonons.add_multi. Default: None.

    Returns
    -------

        dict
            dispersion data.
    """

    import yaml

    # load data

    with open(filename, 'r') as f:
        data = yaml.safe_load(f)

    x = [d['distance'] for d in data['phonon']]
    qp = [q['q-position'] for q in data['phonon']]
    d2, ticks = get_path(data)
    eigs = [[b['frequency'] for b in p['band']] for p in data['phonon']]

    # scale data to other path

    if xdata is not None:
        d1 = xdata['tick_position']
        n = 0
        for i, d0 in enumerate(x):
            while n <= len(d2) and not (d0 >= d2[n] and d0 <= d2[n + 1]):
                n += 1
            x[i] = d1[n] + ((d0 - d2[n]) * (d1[n+1] - d1[n]) / \
                                           (d2[n+1] - d2[n]))
    else:
        d1 = d2

    conversions = settings.phonopy_conversions()
    if 'frequency' in conversions:
        eigs *= conversions['frequency']

    units = tp.settings.units()
    data2 = {
        'x': x,
        'qpoint': qp,
        'frequency': eigs,
        'tick_position': d1,
        'tick_label': ticks,
        'meta': {
            'phonon_dispersion_source': 'phonopy',
            'units': {
                'frequency': units['frequency']
            }
        }
    }

    return data2