コード例 #1
0
ファイル: kpoints.py プロジェクト: suthzx/pyDFTutils
def cubic_kpath():
    special_path = special_paths['cubic']
    points = special_points['cubic']
    paths = parse_path_string(special_path)
    special_kpts = [points[k] for k in paths[0]]
    kpts, xs, xspecial = bandpath(special_kpts, cell=np.eye(3), npoints=500)
    return kpts, xs, xspecial
コード例 #2
0
ファイル: kpoints.py プロジェクト: MePhFPSP/pyDFTutils
def cubic_kpath(npoints=500, name=True):
    """
    return the kpoint path for cubic
    Parameters:
    ----------------
    npoints: int
        number of points.

    Returns:
    -----------------
    kpts:
        kpoints
    xs:
        x cordinates for plot
    xspecial:
        x cordinates for special k points
    """
    special_path = special_paths['cubic']
    points = special_points['cubic']
    paths = parse_path_string(special_path)
    special_kpts = [points[k] for k in paths[0]]
    kpts, xs, xspecial = bandpath(special_kpts,
                                  cell=np.eye(3),
                                  npoints=npoints)
    if not name:
        return kpts, xs, xspecial
    else:
        return kpts, xs, xspecial, special_path
コード例 #3
0
    def set_spectrum(self, bandpath=None, reference=None):
        bands = self.bands
        if bandpath != None:
            self.set_bandpath(bandpath)
        bp = parse_path_string(self.bandpath.path)
        jumps = []
        kps = []
        occs = []
        kpoint_axis = []
        kpoint_labels = []
        label_coords = []
        spectrum = []
        icell_cv = 2 * np.pi * np.linalg.pinv(self.structure.cell).T
        for segment in bp:
            kpoint_labels.append(segment[0])
            label_coords.append(
                label_coords[-1] if len(label_coords) > 0 else 0.0)
            for s1, s2 in zip(segment[:-1], segment[1:]):
                energies = bands[(s1, s2)].eigenvalues
                kpoints = np.dot(bands[(s1, s2)].kpoints, icell_cv)
                occ = bands[(s1, s2)].occupations
                kstep = np.linalg.norm(kpoints[-1, :] - kpoints[0, :])
                kaxis = np.linspace(0, kstep,
                                    kpoints.shape[0]) + label_coords[-1]
                kstep += label_coords[-1]
                spectrum.append(energies)
                kps.append(kpoints)
                occs.append(occ)
                kpoint_axis.append(kaxis)
                label_coords.append(kstep)
                kpoint_labels.append(s2)
            jumps.append(label_coords[-1])
        jumps = jumps[:-1]

        spectrum = np.concatenate(spectrum, axis=0)
        kps = np.concatenate(kps, axis=0)
        kpoint_axis = np.concatenate(kpoint_axis, axis=0)
        occs = np.concatenate(occs, axis=0)

        fermi_level = self.fermi_level.soc if self.soc else self.fermi_level.scalar
        self.set_energy_reference(reference, self.soc)
        reference, shift = self.energy_reference
        sp = BandSpectrum(
            atoms=self.structure.atoms,
            kpoints=kps,
            kpoint_axis=kpoint_axis,
            eigenvalues=spectrum,
            occupations=occs,
            label_coords=label_coords,
            kpoint_labels=kpoint_labels,
            jumps=jumps,
            fermi_level=fermi_level,
            reference=reference,
            shift=shift,
            bandpath=bandpath,
        )
        self._spectrum = sp
コード例 #4
0
ファイル: __init__.py プロジェクト: JaniceLC/aseplayground
    def special_point_names(self):
        """Return all special point names as a list of strings.

        >>> BCT(3, 5).special_point_names
        ['G', 'N', 'P', 'S', 'S1', 'X', 'Y', 'Y1', 'Z']
        """
        labels = parse_path_string(self._variant.special_point_names)
        assert len(labels) == 1  # list of lists
        return labels[0]
コード例 #5
0
ファイル: reciprocal.py プロジェクト: martin-stoehr/ase-devel
def atoms2bandpath(atoms,
                   path='default',
                   k_points=False,
                   ibz_k_points=False,
                   dimension=3,
                   verbose=False):
    cell = atoms.get_cell()
    icell = atoms.get_reciprocal_cell()

    try:
        cs = crystal_structure_from_cell(cell)
    except ValueError:
        cs = None

    if verbose:
        if cs:
            print('Crystal:', cs)
            print('Special points:', special_paths[cs])
        print('Lattice vectors:')
        for i, v in enumerate(cell):
            print('{}: ({:16.9f},{:16.9f},{:16.9f})'.format(i + 1, *v))
        print('Reciprocal vectors:')
        for i, v in enumerate(icell):
            print('{}: ({:16.9f},{:16.9f},{:16.9f})'.format(i + 1, *v))

    # band path
    special_points = None
    if path:
        if path == 'default':
            path = special_paths[cs]
        paths = []
        special_points = get_special_points(cell)
        for names in parse_path_string(path):
            points = []
            for name in names:
                points.append(np.dot(icell.T, special_points[name]))
            paths.append((names, points))
    else:
        paths = None

    # k points
    points = None
    if atoms.calc is not None and hasattr(atoms.calc, 'get_bz_k_points'):
        bzk = atoms.calc.get_bz_k_points()
        if path is None:
            try:
                size, offset = get_monkhorst_pack_size_and_offset(bzk)
            except ValueError:
                # This was not a MP-grid.  Must be a path in the BZ:
                path = ''.join(labels_from_kpts(bzk, cell)[2])

        if k_points:
            points = bzk
        elif ibz_k_points:
            points = atoms.calc.get_ibz_k_points()

    return BandPath(cell, kpts=points, special_points=special_points)
コード例 #6
0
ファイル: plot.py プロジェクト: wangvei/TB2J
def mybandpath(path, cell, npoints=50, eps=1e-3):
    """Make a list of kpoints defining the path between the given points.

    path: list or str
        Can be:

        * a string that parse_path_string() understands: 'GXL'
        * a list of BZ points: [(0, 0, 0), (0.5, 0, 0)]
        * or several lists of BZ points if the the path is not continuous.
    cell: 3x3
        Unit cell of the atoms.
    npoints: int
        Length of the output kpts list.

    Return list of k-points, list of x-coordinates and list of
    x-coordinates of special points."""

    if isinstance(path, str):
        special = get_special_points(cell,eps=eps)
        paths = []
        for names in parse_path_string(path):
            paths.append([special[name] for name in names])
    elif np.array(path[0]).ndim == 1:
        paths = [path]
    else:
        paths = path

    points = np.concatenate(paths)
    dists = points[1:] - points[:-1]
    lengths = [np.linalg.norm(d) for d in kpoint_convert(cell, skpts_kc=dists)]

    i = 0
    for path in paths[:-1]:
        i += len(path)
        lengths[i - 1] = 0

    length = sum(lengths)
    kpts = []
    x0 = 0
    x = []
    X = [0]
    for P, d, L in zip(points[:-1], dists, lengths):
        n = max(2, int(round(L * (npoints - len(x)) / (length - x0))))

        for t in np.linspace(0, 1, n)[:-1]:
            kpts.append(P + t * d)
            x.append(x0 + t * L)
        x0 += L
        X.append(x0)
    kpts.append(points[-1])
    x.append(x0)

    return np.array(kpts), np.array(x), np.array(X)
コード例 #7
0
    def read_bands(self):
        outputyaml = self.outputdir.joinpath("band.yaml")
        assert outputyaml.exists(), "File band.yaml not found."
        with open(outputyaml, "r") as stream:
            try:
                data = yaml.safe_load(stream)
            except yaml.YAMLError as exc:
                raise Exception(exc)

        labels = data["labels"]
        bpstring = []
        for i, pair in enumerate(labels):
            if i == 0:
                bpstring.append(pair[0])
            elif i == len(labels) - 1:
                bpstring.append(pair[0])
                bpstring.append(pair[1])
            else:
                bpstring.append(pair[0])
        bpstring = "".join(bpstring)
        bpstring = bpstring.replace("|", ",")
        bplist = parse_path_string(bpstring)

        special_points = (self.structure.cell.get_bravais_lattice().bandpath().
                          special_points)
        self._bandpath = BandPath(path=bpstring,
                                  cell=self.structure.cell,
                                  special_points=special_points)

        phon = data["phonon"]
        nqpoints = data["segment_nqpoint"]

        qpoints = np.array([k["q-position"] for k in phon], dtype=np.float32)
        pbands = np.array([[l["frequency"] for l in k["band"]] for k in phon],
                          dtype=np.float32)

        b = namedtuple("band", ["qpoints", "frequencies"])
        count = 0
        bands = {}

        i = 0
        for segment in bplist:
            for pair in zip(segment[:-1], segment[1:]):
                j1, j2 = count, nqpoints[i] + count
                count = j2
                qp = qpoints[j1:j2, :]
                pb = pbands[j1:j2, :]
                bands[pair] = b(qp, pb)
                rev = (pair[1], pair[0])
                bands[rev] = b(qp[::-1], pb[::-1])
                i += 1
        return bands
コード例 #8
0
    def set_spectrum(self, bandpath=None, unit=r"cm$^{-1}$"):
        assert unit in [r"cm$^{-1}$", "Thz"], "Unit not recognized."
        bands = self.bands
        if bandpath != None:
            self.set_bandpath(bandpath)
        bp = parse_path_string(self.bandpath.path)
        jumps = []
        qps = []
        qpoint_axis = []
        qpoint_labels = []
        label_coords = []
        spectrum = []
        icell_cv = 2 * np.pi * np.linalg.pinv(self.structure.cell).T
        for segment in bp:
            qpoint_labels.append(segment[0])
            label_coords.append(
                label_coords[-1] if len(label_coords) > 0 else 0.0)
            for s1, s2 in zip(segment[:-1], segment[1:]):
                freqs = bands[(s1, s2)].frequencies
                qpoints = np.dot(bands[(s1, s2)].qpoints, icell_cv)
                qstep = np.linalg.norm(qpoints[-1, :] - qpoints[0, :])
                qaxis = np.linspace(0, qstep,
                                    qpoints.shape[0]) + label_coords[-1]
                qstep += label_coords[-1]
                spectrum.append(freqs)
                qps.append(qpoints)
                qpoint_axis.append(qaxis)
                label_coords.append(qstep)
                qpoint_labels.append(s2)
            jumps.append(label_coords[-1])
        jumps = jumps[:-1]

        spectrum = np.concatenate(spectrum, axis=0)  # unit in Thz
        # 1 Thz = 33.356 cm^-1
        if unit == r"cm$^{-1}$":
            spectrum *= 33.356
        qps = np.concatenate(qps, axis=0)
        qpoint_axis = np.concatenate(qpoint_axis, axis=0)
        atoms = self.structure.copy()
        sp = PhononSpectrum(
            qpoints=qps,
            qpoint_axis=qpoint_axis,
            frequencies=spectrum,
            atoms=atoms,
            label_coords=label_coords,
            qpoint_labels=qpoint_labels,
            jumps=jumps,
            unit=unit,
            bandpath=bp,
        )
        self._spectrum = sp
コード例 #9
0
def generate_kpath_ase(cell, symprec):

    eig_val_max = np.real(np.linalg.eigvals(cell)).max()
    eps = eig_val_max * symprec

    lattice = crystal_structure_from_cell(cell, eps)
    paths = special_paths.get(lattice, None)
    if paths is None:
        paths = special_paths['orthorhombic']
    paths = parse_path_string(special_paths[lattice])
    points = special_points.get(lattice)
    if points is None:
        try:
            points = get_special_points(cell)
        except Exception:
            return []

    return generate_kpath_parameters(points, paths, 100)
コード例 #10
0
    def get_bandpath_as_aims_strings(self, pbc=[True, True, True]):
        """This function sets up the band path according to Setyawan-Curtarolo conventions.

        Returns:
            list: List of strings containing the k-path sections.
        """
        from ase.dft.kpoints import parse_path_string, kpoint_convert

        atoms = self.structure.atoms
        atoms.pbc = pbc
        path = parse_path_string(
            atoms.cell.get_bravais_lattice(pbc=atoms.pbc).bandpath().path)
        # list Of lists of path segments
        points = atoms.cell.get_bravais_lattice(
            pbc=atoms.pbc).bandpath().special_points
        segments = []
        for seg in path:
            section = [(i, j) for i, j in zip(seg[:-1], seg[1:])]
            segments.append(section)
        output_bands = []
        index = 1
        for seg in segments:
            output_bands.append(
                "## Brillouin Zone section Nr. {:d}\n".format(index))
            for sec in seg:
                dist = np.array(points[sec[1]]) - np.array(points[sec[0]])
                length = np.linalg.norm(
                    kpoint_convert(atoms.cell, skpts_kc=dist))
                npoints = np.int_(np.round(np.asarray(length) * 20))
                vec1 = "{:.6f} {:.6f} {:.6f}".format(*points[sec[0]])
                vec2 = "{:.6f} {:.6f} {:.6f}".format(*points[sec[1]])
                output_bands.append(
                    "{vec1} \t {vec2} \t {npoints} \t {label1} {label2}".
                    format(
                        label1=sec[0],
                        label2=sec[1],
                        npoints=npoints,
                        vec1=vec1,
                        vec2=vec2,
                    ))
            index += 1
        return output_bands
コード例 #11
0
 def set_bandpath(self, bandpathstring):
     new_bandpath = parse_path_string(bandpathstring)
     old_path = self.bandpath
     special_points = old_path.special_points
     pairs = [(s[0], s[1]) for s in self.bands.keys()]
     for segment in new_bandpath:
         assert len(segment) > 1, "A vertex needs at least two points."
         p = zip(segment[:-1], segment[1:])
         for s1, s2 in p:
             assert any(x in pairs for x in ((s1, s2), (
                 s2,
                 s1))), "The k-path {}-{} has not been calculated.".format(
                     s1, s2)
     else:
         new_path = BandPath(
             path=bandpathstring,
             cell=self.structure.cell,
             special_points=special_points,
         )
     self._bandpath = new_path
コード例 #12
0
    ax.view_init(azim=azim / pi * 180, elev=elev / pi * 180)


for X, cell in [('cubic', np.eye(3)), ('fcc', [[0, 1, 1], [1, 0, 1], [1, 1,
                                                                      0]]),
                ('bcc', [[-1, 1, 1], [1, -1, 1], [1, 1, -1]]),
                ('tetragonal', [[1, 0, 0], [0, 1, 0], [0, 0, 1.3]]),
                ('orthorhombic', [[1, 0, 0], [0, 1.2, 0], [0, 0, 1.4]]),
                ('hexagonal', [[1, 0, 0], [-0.5, 3**0.5 / 2, 0], [0, 0, 1]]),
                ('monoclinic', [[1, 0, 0], [0, 1, 0], [0, 0.2, 1]])]:

    icell = np.linalg.inv(cell)
    print(cell, X)
    special_points = get_special_points(cell, X)
    paths = []
    for names in parse_path_string(special_paths[X]):
        points = []
        for name in names:
            points.append(np.dot(icell, special_points[name]))
        paths.append((names, points))

    if X == 'bcc':
        scale = 0.6
        elev = pi / 13
    else:
        scale = 1
        elev = None

    plot(cell, paths, elev, scale)
    plt.savefig(X + '.svg')
コード例 #13
0
def bz3d_plot(cell, vectors=False, paths=None, points=None, ax=None,
              elev=None, scale=1, repeat=None, transformations=None,
              hide_ax=True, **kwargs):
    """
    For now this is lifted from ase.dft.bz.bz3d_plot with some modifications. All copyright and
    licensing terms for this and bz2d_plot are those of the current release of ASE
    (Atomic Simulation Environment).

    :param cell:
    :param vectors:
    :param paths:
    :param points:
    :param elev:
    :param scale:
    :return:
    """
    try:
        from ase.dft.bz import bz_vertices  # dynamic because we do not require ase
    except ImportError:
        warnings.warn('You will need to install ASE (Atomic Simulation Environment) to use this feature.')
        raise ImportError('You will need to install ASE before using Brillouin Zone plotting')

    class Arrow3D(FancyArrowPatch):
        def __init__(self, xs, ys, zs, *args, **kwargs):
            FancyArrowPatch.__init__(self, (0, 0), (0, 0), *args, **kwargs)
            self._verts3d = xs, ys, zs

        def draw(self, renderer):
            xs3d, ys3d, zs3d = self._verts3d
            xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
            self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))
            FancyArrowPatch.draw(self, renderer)

    icell = np.linalg.inv(cell).T
    kpoints = points

    if isinstance(paths, str):
        from ase.dft.kpoints import (get_special_points, special_paths, parse_path_string,
                                     crystal_structure_from_cell)
        special_points = get_special_points(cell)
        structure = crystal_structure_from_cell(cell)

        path_string = special_paths[structure] if paths == 'all' else paths
        paths = []
        for names in parse_path_string(path_string):
            points = []
            for name in names:
                points.append(np.dot(icell.T, special_points[name]))
                paths.append((names, points))

    if ax is None:
        fig = plt.figure(figsize=(5, 5))
        ax = fig.gca(projection='3d')

    azim = np.pi / 5
    elev = elev or np.pi / 6
    x = np.sin(azim)
    y = np.cos(azim)
    view = [x * np.cos(elev), y * np.cos(elev), np.sin(elev)]

    bz1 = bz_vertices(icell)

    maxp = 0.0

    if repeat is None:
        repeat = (1, 1, 1,)

    dx, dy, dz = icell[0], icell[1], icell[2]
    rep_x, rep_y, rep_z = repeat

    if isinstance(rep_x, int):
        rep_x = (0, rep_x)
    if isinstance(rep_y, int):
        rep_y = (0, rep_y)
    if isinstance(rep_z, int):
        rep_z = (0, rep_z)

    c = kwargs.pop('c', 'k')
    c = kwargs.pop('color', c)


    for ix, iy, iz in itertools.product(range(*rep_x), range(*rep_y), range(*rep_z)):
        delta = dx * ix + dy * iy + dz * iz

        for points, normal in bz1:
            color = c

            if np.dot(normal, view) < 0:
                ls = ':'
            else:
                ls = '-'

            cosines = np.dot(icell, normal)/ np.linalg.norm(normal) / np.linalg.norm(icell, axis=1)
            for idx, cosine in enumerate(cosines):
                if np.abs(np.abs(cosine) - 1) < 1e-6 and False: # debugging this
                    tup = [rep_x, rep_y, rep_z][idx]
                    current = [ix, iy, iz][idx]

                    if cosine < 0:
                        current = current - 1

                    if tup[0] < current + 1 < tup[1]:
                        color = (1, 1, 1, 0)

                    if current + 1 != tup[1] and current != tup[0]:
                        ls = ':'
                        color='blue'

            x, y, z = np.concatenate([points, points[:1]]).T
            x, y, z = x + delta[0], y + delta[1], z + delta[2]

            ax.plot(x, y, z, c=color, ls=ls, **kwargs)
            maxp = max(maxp, points.max())

    if vectors:
        ax.add_artist(Arrow3D([0, icell[0, 0]],
                              [0, icell[0, 1]],
                              [0, icell[0, 2]],
                              mutation_scale=20, lw=1,
                              arrowstyle='-|>', color='k'))
        ax.add_artist(Arrow3D([0, icell[1, 0]],
                              [0, icell[1, 1]],
                              [0, icell[1, 2]],
                              mutation_scale=20, lw=1,
                              arrowstyle='-|>', color='k'))
        ax.add_artist(Arrow3D([0, icell[2, 0]],
                              [0, icell[2, 1]],
                              [0, icell[2, 2]],
                              mutation_scale=20, lw=1,
                              arrowstyle='-|>', color='k'))
        maxp = max(maxp, 0.6 * icell.max())

    if paths is not None:
        for names, points in paths:
            x, y, z = np.array(points).T
            ax.plot(x, y, z, c='r', ls='-')

            for name, point in zip(names, points):
                x, y, z = point
                if name == 'G':
                    name = '\\Gamma'
                elif len(name) > 1:
                    name = name[0] + '_' + name[1]
                ax.text(x, y, z, '$' + name + '$',
                        ha='center', va='bottom', color='r')

    if kpoints is not None:
        for p in kpoints:
            ax.scatter(p[0], p[1], p[2], c='b')

    if hide_ax:
        ax.set_axis_off()
        ax.autoscale_view(tight=True)

    s = maxp / 0.5 * 0.45 * scale
    ax.set_xlim(-s, s)
    ax.set_ylim(-s, s)
    ax.set_zlim(-s, s)
    ax.set_aspect('equal')

    ax.view_init(azim=azim / np.pi * 180, elev=elev / np.pi * 180)
コード例 #14
0
ファイル: bravais.py プロジェクト: btodac/ase
 def special_point_names(self):
     labels = parse_path_string(self._variant.special_point_names)
     assert len(labels) == 1  # list of lists
     return labels[0]
コード例 #15
0
ファイル: bz.py プロジェクト: rosswhitfield/ase
    ax.view_init(azim=azim / pi * 180, elev=elev / pi * 180)


for X, cell in [
    ('cubic', np.eye(3)),
    ('fcc', [[0, 1, 1], [1, 0, 1], [1, 1, 0]]),
    ('bcc', [[-1, 1, 1], [1, -1, 1], [1, 1, -1]]),
    ('tetragonal', [[1, 0, 0], [0, 1, 0], [0, 0, 1.3]]),
    ('orthorhombic', [[1, 0, 0], [0, 1.2, 0], [0, 0, 1.4]]),
    ('hexagonal', [[1, 0, 0], [-0.5, 3**0.5 / 2, 0], [0, 0, 1]]),
    ('monoclinic', [[1, 0, 0], [0, 1, 0], [0, 0.2, 1]])]:

    icell = np.linalg.inv(cell)
    special_points = get_special_points(X, cell)
    paths = []
    for names in parse_path_string(special_paths[X]):
        points = []
        for name in names:
            points.append(np.dot(icell, special_points[name]))
        paths.append((names, points))

    if X == 'bcc':
        scale = 0.6
        elev = pi / 13
    else:
        scale = 1
        elev = None

    plot(cell, paths, elev, scale)
    plt.savefig(X + '.svg')
コード例 #16
0
def bz2d_plot(cell, vectors=False, paths=None, points=None, repeat=None, ax=None,
              transformations=None, offset=None, hide_ax=True, set_equal_aspect=True,
              **kwargs):
    """
    This piece of code modified from ase.ase.dft.bz.py:bz2d_plot and follows copyright and license for ASE.

    Plots a Brillouin zone corresponding to a given unit cell
    :param cell:
    :param vectors:
    :param paths:
    :param points:
    :return:
    """
    kpoints = points
    bz1, icell, cell = twocell_to_bz1(cell)
    if ax is None:
        ax = plt.axes()

    if isinstance(paths, str):
        from ase.dft.kpoints import (get_special_points, special_paths, parse_path_string,
                                     crystal_structure_from_cell)
        special_points = get_special_points(cell)
        structure = crystal_structure_from_cell(cell)

        path_string = special_paths[structure] if paths == 'all' else paths
        paths = []
        for names in parse_path_string(path_string):
            points = []
            for name in names:
                points.append(np.dot(icell.T, special_points[name]))
                paths.append((names, points))

    maxp = 0.0
    c = kwargs.pop('c', 'k')
    c = kwargs.pop('color', c)
    ls = kwargs.pop('ls', kwargs.pop('linestyle', '-'))

    for points, normal in bz1:
        points = apply_transformations(points, transformations)
        x, y, z = np.concatenate([points, points[:1]]).T

        ax.plot(x, y, c=c, ls=ls, **kwargs)
        maxp = max(maxp, points.max())

    if repeat is not None:
        dx, dy = icell[0], icell[1]

        rep_x, rep_y = repeat
        if isinstance(rep_x, int):
            rep_x = (0, rep_x)
        if isinstance(rep_y, int):
            rep_y = (0, rep_y)

        for ix, iy in itertools.product(range(*rep_x), range(*rep_y)):
            delta = dx * ix + dy * iy

            for points, normal in bz1:
                x, y, z = np.concatenate([points, points[:1]]).T
                x, y = x + delta[0], y + delta[1]
                x, y, z = apply_transformations(np.asarray([x, y, z]).T, transformations).T

                c = kwargs.pop('c', 'k')
                c = kwargs.pop('color', c)
                ax.plot(x, y, c=c, ls=ls, **kwargs)
                maxp = max(maxp, points.max())

    if vectors:
        ax.arrow(0, 0, icell[0, 0], icell[0, 1],
                 lw=1, color='k',
                 length_includes_head=True,
                 head_width=0.03, head_length=0.05)
        ax.arrow(0, 0, icell[1, 0], icell[1, 1],
                 lw=1, color='k',
                 length_includes_head=True,
                 head_width=0.03, head_length=0.05)

    if paths is not None:
        annotate_special_paths(ax, paths, offset=offset, transformations=transformations)

    if kpoints is not None:
        for p in kpoints:
            ax.scatter(p[0], p[1], c='b')

    if hide_ax:
        ax.set_axis_off()
        ax.autoscale_view(tight=True)

    if set_equal_aspect:
        ax.set_aspect('equal')
コード例 #17
0
ファイル: BZ.py プロジェクト: OMalenfantThuot/bigdft-suite
 def __init__(self,astruct,mesh,evals,fermi_energy):
     import spglib,numpy
     cell=astruct_to_cell(astruct)
     self.lattice=cell[0]
     #celltmp=[ a if a!=float('inf') else 1.0 for a in astruct['cell']]
     #self.lattice=numpy.diag(celltmp)
     #print 'lattice',self.lattice
     #pos=[ [ a/b if b!=float('inf') else 0.0 for a,b in zip(at.values()[0], celltmp)]for at in astruct['positions']]
     #atoms=[ at.keys()[0] for at in astruct['positions']]
     #ianames,iatype=numpy.unique(atoms,return_inverse=True) #[1,]*4+[2,]*4 #we should write a function for the iatype
     #print 'iatype', iatype
     #cell=(self.lattice,pos,iatype)
     safe_print('spacegroup',spglib.get_spacegroup(cell, symprec=1e-5))
     #then define the pathes and special points
     import ase.dft.kpoints as ase
     #we should adapt the 'cubic'
     cell_tmp=astruct['cell']
     #print 'cell',cell_tmp,numpy.allclose(cell_tmp,[cell_tmp[0],]*len(cell_tmp))
     if numpy.allclose(cell_tmp,[cell_tmp[0],]*len(cell_tmp)):
         lattice_string='cubic'
     else:
         lattice_string='orthorhombic'
     safe_print('Lattice found:',lattice_string)
     self.special_points=ase.get_special_points(lattice_string, self.lattice, eps=0.0001)
     self.special_paths=ase.parse_path_string(ase.special_paths[lattice_string])
     self.fermi_energy=fermi_energy
     #dataset = spglib.get_symmetry_dataset(cell, symprec=1e-3)
     #print dataset
     #the shift has also to be put if present
     mapping, grid = spglib.get_ir_reciprocal_mesh(mesh, cell, is_shift=[0, 0, 0])
     lookup=[]
     for ikpt in numpy.unique(mapping):
         ltmp=[]
         for ind, (m, g) in enumerate(zip(mapping, grid)):
             if m==ikpt:
                 ltmp.append((g,ind))
         lookup.append(ltmp)
     safe_print('irreductible k-points',len(lookup))
     #print 'mapping',mapping
     #print 'grid',len(grid),numpy.max(grid)
     coords=numpy.array(grid, dtype = numpy.float)/mesh
     #print 'coords',coords
     #print 'shape',coords.shape
     #print grid #[ x+mesh[0]*y+mesh[0]*mesh[1]*z for x,y,z in grid]
     #brillouin zone
     kp=numpy.array([ k.kpt for k in evals])
     ourkpt=numpy.rint(kp*(numpy.array(mesh))).astype(int)
     #print ourkpt
     bz=numpy.ndarray((coords.shape[0],evals[0].size),dtype=float)
     #print bz
     shift=(numpy.array(mesh)-1)/2
     #print 'shift',shift
     for ik in lookup:
         irrk=None
         for orbs,bzk in zip(evals,ourkpt):
             for (kt,ind) in ik:
                 if (bzk==kt).all():
                     irrk=orbs
                     #print 'hello',orbs.kpt,kt
                     break 
             if irrk is not None: break
         if irrk is None:
             safe_print( 'error in ik',ik)
             safe_print( 'our',ourkpt)
             safe_print( 'spglib',grid)
             safe_print( 'mapping',mapping)
         for (kt,ind) in ik:
             #r=kt+shift
             #ind=numpy.argwhere([(g==kt).all() for g in grid])
             #print 'ik',kt,r,ind
             #print irrk.shape, bz.shape
             #bz[r[0],r[1],r[2],:]=irrk.reshape(irrk.size)
             bz[ind,:]=irrk.reshape(irrk.size)
     #duplicate coordinates for the interpolation
     bztmp=bz#.reshape((mesh[0]*mesh[1]*mesh[2], -1))
     #print bztmp
     ndup=7
     duplicates=[[-1,0,0],[1,0,0],[0,-1,0],[0,1,0],[0,0,-1],[0,0,1]]
     bztot=numpy.ndarray((ndup,bztmp.shape[0],bztmp.shape[1]))
     bztot[0,:,:]=bztmp
     ctot=numpy.ndarray((ndup,coords.shape[0],coords.shape[1]))
     ctot[0,:,:]=coords
     for i,sh in enumerate(duplicates):
         bztot[i+1,:,:]=bztmp
         ctot[i+1,:,:]=coords+sh
         #print 'coors',coords,coords+[1.0,0,0]
     bztot=bztot.reshape((ndup*bztmp.shape[0], -1))
     ctot=ctot.reshape((ndup*coords.shape[0], -1))
     import scipy.interpolate.interpnd as interpnd
     self.interpolator=interpnd.LinearNDInterpolator(ctot,bztot)
     #sanity check of the interpolation
     sanity=0.0
     for kpt in evals:
         diff=numpy.ravel(numpy.ravel(kpt)-numpy.ravel(self.interpolator([ kpt.kpt])))
         sanity=max(sanity,numpy.dot(diff,diff))
     print('Interpolation bias',sanity)
コード例 #18
0
ファイル: reciprocal.py プロジェクト: essil1/ase-laser
def plot_reciprocal_cell(atoms,
                         path='default',
                         k_points=False,
                         ibz_k_points=False,
                         plot_vectors=True,
                         dimension=3,
                         output=None,
                         verbose=False):
    import matplotlib.pyplot as plt

    cell = atoms.get_cell()
    icell = atoms.get_reciprocal_cell()

    try:
        cs = crystal_structure_from_cell(cell)
    except ValueError:
        cs = None

    if verbose:
        if cs:
            print('Crystal:', cs)
            print('Special points:', special_paths[cs])
        print('Lattice vectors:')
        for i, v in enumerate(cell):
            print('{}: ({:16.9f},{:16.9f},{:16.9f})'.format(i + 1, *v))
        print('Reciprocal vectors:')
        for i, v in enumerate(icell):
            print('{}: ({:16.9f},{:16.9f},{:16.9f})'.format(i + 1, *v))

    # band path
    if path:
        if path == 'default':
            path = special_paths[cs]
        paths = []
        special_points = get_special_points(cell)
        for names in parse_path_string(path):
            points = []
            for name in names:
                points.append(np.dot(icell.T, special_points[name]))
            paths.append((names, points))
    else:
        paths = None

    # k points
    points = None
    if atoms.calc is not None and hasattr(atoms.calc, 'get_bz_k_points'):
        bzk = atoms.calc.get_bz_k_points()
        if path is None:
            try:
                size, offset = get_monkhorst_pack_size_and_offset(bzk)
            except ValueError:
                # This was not a MP-grid.  Must be a path in the BZ:
                path = ''.join(labels_from_kpts(bzk, cell)[2])

        if k_points:
            points = bzk
        elif ibz_k_points:
            points = atoms.calc.get_ibz_k_points()
        if points is not None:
            for i in range(len(points)):
                points[i] = np.dot(icell.T, points[i])

    kwargs = {
        'cell': cell,
        'vectors': plot_vectors,
        'paths': paths,
        'points': points
    }

    if dimension == 1:
        bz1d_plot(**kwargs)
    elif dimension == 2:
        bz2d_plot(**kwargs)
    else:
        bz3d_plot(interactive=True, **kwargs)

    if output:
        plt.savefig(output)
    else:
        plt.show()
コード例 #19
0
    def set_spectrum(self, bandpath=None, reference=None):
        """ Sets :class:`~aimstools.bandstructures.mulliken_bandstructure.MullikenSpectrum` for a given bandpath.
        
        Bandpath should be ASE-formatted string, e.g., "GMKG,A", where the "," denotes jumps.
        """
        bands = self.bands
        atoms = self.structure.copy()
        start = time.time()
        if bandpath != None:
            self.set_bandpath(bandpath)
        bp = parse_path_string(self.bandpath.path)
        jumps = []
        kps = []
        occs = []
        kpoint_axis = []
        kpoint_labels = []
        label_coords = []
        spectrum = []
        icell_cv = 2 * np.pi * np.linalg.pinv(self.structure.cell).T
        contributions = []
        for segment in bp:
            kpoint_labels.append(segment[0])
            label_coords.append(
                label_coords[-1] if len(label_coords) > 0 else 0.0)
            for s1, s2 in zip(segment[:-1], segment[1:]):
                if (s1, s2) in bands.keys():
                    data = bands[(s1, s2)].data
                    kpoints = np.dot(bands[(s1, s2)].kpoints, icell_cv)
                    energies = data[0, :, :, :,
                                    0]  # (nkpoints, nspins, nstates)
                    occ = data[0, :, :, :, 1]  # (nkpoints, nspins, nstates)
                    con = data[:, :, :, :,
                               2:]  # (natoms, nkpoints, nspins, nstates, [tot, s, p, d, f])
                elif (s1, s2) in [(k, j) for j, k in bands.keys()]:
                    data = bands[(s2, s1)].data
                    kpoints = np.dot(bands[(s2, s1)].kpoints, icell_cv)[::-1]
                    energies = data[0, :, :, :,
                                    0]  # (nkpoints, nspins, nstates)
                    energies = energies[::-1, :, :]
                    occ = data[0, :, :, :, 1]  # (nkpoints, nspins, nstates)
                    occ = occ[::-1, :, :]
                    con = data[:, :, :, :,
                               2:]  # (natoms, nkpoints, nspins, nstates, [tot, s, p, d, f])
                    con = con[:, ::-1, ...]
                else:
                    raise Exception(
                        "Neither {}-{} nor {}-{} were found.".format(
                            s1, s2, s2, s1))

                kstep = np.linalg.norm(kpoints[-1, :] - kpoints[0, :])
                kaxis = np.linspace(0, kstep,
                                    kpoints.shape[0]) + label_coords[-1]
                kstep += label_coords[-1]
                spectrum.append(energies)
                kps.append(kpoints)
                occs.append(occ)
                contributions.append(con)
                kpoint_axis.append(kaxis)
                label_coords.append(kstep)
                kpoint_labels.append(s2)
            jumps.append(label_coords[-1])
        jumps = jumps[:-1]
        spectrum = np.concatenate(spectrum, axis=0)
        kps = np.concatenate(kps, axis=0)
        kpoint_axis = np.concatenate(kpoint_axis, axis=0)
        occs = np.concatenate(occs, axis=0)
        cons = np.concatenate(contributions, axis=1)
        fermi_level = self.fermi_level.soc if self.soc else self.fermi_level.scalar
        self.set_energy_reference(reference, self.soc)
        reference, shift = self.energy_reference
        spec = MullikenSpectrum(
            atoms=atoms,
            kpoints=kps,
            kpoint_axis=kpoint_axis,
            eigenvalues=spectrum,
            occupations=occs,
            contributions=cons,
            label_coords=label_coords,
            kpoint_labels=kpoint_labels,
            jumps=jumps,
            fermi_level=fermi_level,
            reference=reference,
            shift=shift,
            bandpath=bp,
        )
        end = time.time()
        logger.info(
            "Creating spectrum from bands took {:.2f} seconds.".format(end -
                                                                       start))
        self._spectrum = spec
コード例 #20
0
def plot_magnon_band(ham,
                     kvectors=np.array([[0, 0, 0], [0.5, 0, 0], [0.5, 0.5, 0],
                                        [0, 0, 0], [.5, .5, .5]]),
                     knames=['$\Gamma$', 'X', 'M', '$\Gamma$', 'R'],
                     supercell_matrix=None,
                     npoints=100,
                     color='red',
                     ax=None,
                     eps=1e-3,
                     kpath_fname=None):
    if ax is None:
        fig, ax = plt.subplots()
    if knames is None or kvectors is None:
        from ase.build.tools import niggli_reduce_cell
        rcell, M = niggli_reduce_cell(ham.cell)
        fcell = fix_cell(ham.cell, eps=eps)
        lattice_type = crystal_structure_from_cell(rcell,
                                                   eps=eps,
                                                   niggli_reduce=False)
        labels = parse_path_string(special_paths[lattice_type])
        knames = [item for sublist in labels for item in sublist]
        kpts, x, X = bandpath(special_paths[lattice_type],
                              rcell,
                              npoints=npoints,
                              eps=1e-8)

        spk = get_special_points(ham.cell, eps=1e-8)
    else:
        kpts, x, X = bandpath(kvectors, fix_cell(ham.cell), npoints)
        spk = dict(zip(knames, kvectors))

    if supercell_matrix is not None:
        kvectors = [np.dot(k, supercell_matrix) for k in kvectors]

    qsolver = QSolver(hamiltonian=ham)
    evals, evecs = qsolver.solve_all(kpts, eigen_vectors=True)
    nbands = evals.shape[1]
    #evecs

    imin = np.argmin(evals[:, 0])
    emin = np.min(evals[:, 0])
    nspin = evals.shape[1] // 3
    evec_min = evecs[imin, :, 0].reshape(nspin, 3)

    # write information to file
    if kpath_fname is not None:
        with open(kpath_fname, 'w') as myfile:
            myfile.write("K-points:\n")
            for name, k in spk.items():
                myfile.write("%s: %s\n" % (name, k))
            myfile.write("\nThe energy minimum is at:")
            myfile.write("%s\n" % kpts[np.argmin(evals[:, 0])])
            for i, ev in enumerate(evec_min):
                myfile.write("spin %s: %s \n" % (i, ev / np.linalg.norm(ev)))
    print("\nThe energy minimum is at:")
    print("%s\n" % kpts[np.argmin(evals[:, 0])])
    print("\n The ground state is:")
    for i, ev in enumerate(evec_min):
        print("spin %s: %s" % (i, ev / np.linalg.norm(ev)))

    for i in range(nbands):
        ax.plot(x, (evals[:, i] - emin) / 1.6e-22)
    ax.set_xlabel('Q-point')
    ax.set_ylabel('Energy (meV)')
    ax.set_xlim(x[0], x[-1])
    ax.set_ylim(0)
    ax.set_xticks(X)
    ax.set_xticklabels(knames)

    for x in X:
        ax.axvline(x, linewidth=0.6, color='gray')
    return ax