Exemple #1
0
    def bandpath(self, path=None, npoints=None, special_points=None,
                 density=None, transformation=None):
        """Return a :class:`~ase.dft.kpoints.BandPath` for this lattice.

        See :meth:`ase.cell.Cell.bandpath` for description of parameters.

        >>> BCT(3, 5).bandpath()
        BandPath(path='GXYSGZS1NPY1Z,XP', cell=[3x3], special_points={GNPSS1XYY1Z}, kpts=[51x3])

        .. note:: This produces the standard band path following AFlow
           conventions.  If your cell does not follow this convention,
           you will need :meth:`ase.cell.Cell.bandpath` instead or
           the kpoints may not correspond to your particular cell.

        """
        if special_points is None:
            special_points = self.get_special_points()

        if path is None:
            path = self._variant.special_path
        elif not isinstance(path, str):
            from ase.dft.kpoints import resolve_custom_points
            special_points = dict(special_points)
            path = resolve_custom_points(path, special_points, self._eps)

        cell = self.tocell()
        if transformation is not None:
            cell = transformation.dot(cell)

        bandpath = BandPath(cell=cell, path=path,
                            special_points=special_points)
        return bandpath.interpolate(npoints=npoints, density=density)
Exemple #2
0
    def bandpath(self,
                 path=None,
                 npoints=None,
                 special_points=None,
                 density=None,
                 transformation=None):
        """Return a :class:`~ase.dft.kpoints.BandPath` for this lattice.

        See :meth:`ase.cell.Cell.bandpath` for description of parameters.

        >>> BCT(3, 5).bandpath()
        BandPath(path='GXYSGZS1NPY1Z,XP', cell=[3x3], special_points={GNPSS1XYY1Z}, kpts=[51x3])
        """
        if special_points is None:
            special_points = self.get_special_points()

        if path is None:
            path = self._variant.special_path
        elif not isinstance(path, str):
            from ase.dft.kpoints import resolve_custom_points
            special_points = dict(special_points)
            path = resolve_custom_points(path, special_points, self._eps)

        cell = self.tocell()
        if transformation is not None:
            cell = transformation.dot(cell)

        bandpath = BandPath(cell=cell,
                            path=path,
                            special_points=special_points)
        return bandpath.interpolate(npoints=npoints, density=density)
Exemple #3
0
def get_band_structure(atoms=None, calc=None, path=None, reference=None):
    """Create band structure object from Atoms or calculator."""
    # path and reference are used internally at the moment, but
    # the exact implementation will probably change.  WIP.
    #
    # XXX We throw away info about the bandpath when we create the calculator.
    # If we have kept the bandpath, we can provide it as an argument here.
    # It would be wise to check that the bandpath kpoints are the same as
    # those stored in the calculator.
    atoms = atoms if atoms is not None else calc.atoms
    calc = calc if calc is not None else atoms.calc

    kpts = calc.get_ibz_k_points()

    energies = []
    for s in range(calc.get_number_of_spins()):
        energies.append(
            [calc.get_eigenvalues(kpt=k, spin=s) for k in range(len(kpts))])
    energies = np.array(energies)

    if path is None:
        from ase.dft.kpoints import resolve_custom_points, find_bandpath_kinks
        path = atoms.cell.bandpath(npoints=0)
        # Kpoints are already evaluated, we just need to put them into
        # the path (whether they fit our idea of what the path is, or not).
        #
        # Depending on how the path was established, the kpoints might
        # be valid high-symmetry points, but since there are multiple
        # high-symmetry points of each type, they may not coincide
        # with ours if the bandpath was generated by another code.
        #
        # Here we hack it so the BandPath has proper points even if they
        # come from some weird source.
        #
        # This operation (manually hacking the bandpath) is liable to break.
        # TODO: Make it available as a proper (documented) bandpath method.
        kinks = find_bandpath_kinks(atoms.cell, kpts, eps=1e-5)
        pathspec = resolve_custom_points(kpts[kinks],
                                         path.special_points,
                                         eps=1e-5)
        path.kpts = kpts
        path.path = pathspec

    # XXX If we *did* get the path, now would be a good time to check
    # that it matches the cell!  Although the path can only be passed
    # because we internally want to not re-evaluate the Bravais
    # lattice type.  (We actually need an eps parameter, too.)

    if reference is None:
        # Fermi level should come from the GS calculation, not the BS one!
        reference = calc.get_fermi_level()

    if reference is None:
        # Fermi level may not be available, e.g., with non-Fermi smearing.
        # XXX Actually get_fermi_level() should raise an error when Fermi
        # level wasn't available, so we should fix that.
        reference = 0.0

    return BandStructure(path=path, energies=energies, reference=reference)
Exemple #4
0
    def bandpath(
            self,
            path: str = None,
            npoints: int = None,
            *,
            density: float = None,
            special_points: Mapping[str, Sequence[float]] = None,
            eps: float = 2e-4,
            pbc: Union[bool,
                       Sequence[bool]] = True) -> "ase.dft.kpoints.BandPath":
        """Build a :class:`~ase.dft.kpoints.BandPath` for this cell.

        If special points are None, determine the Bravais lattice of
        this cell and return a suitable Brillouin zone path with
        standard special points.

        If special special points are given, interpolate the path
        directly from the available data.

        Parameters:

        path: string
            String of special point names defining the path, e.g. 'GXL'.
        npoints: int
            Number of points in total.  Note that at least one point
            is added for each special point in the path.
        density: float
            density of kpoints along the path in Å⁻¹.
        special_points: dict
            Dictionary mapping special points to scaled kpoint coordinates.
            For example ``{'G': [0, 0, 0], 'X': [1, 0, 0]}``.
        eps: float
            Tolerance for determining Bravais lattice.
        pbc: three bools
            Whether cell is periodic in each direction.  Normally not
            necessary.  If cell has three nonzero cell vectors, use
            e.g. pbc=[1, 1, 0] to request a 2D bandpath nevertheless.

        Example
        -------
        >>> cell = Cell.fromcellpar([4, 4, 4, 60, 60, 60])
        >>> cell.bandpath('GXW', npoints=20)
        BandPath(path='GXW', cell=[3x3], special_points={GKLUWX}, kpts=[20x3])

        """
        # TODO: Combine with the rotation transformation from bandpath()

        cell = self.uncomplete(pbc)

        if special_points is None:
            from ase.lattice import identify_lattice
            lat, op = identify_lattice(cell, eps=eps)
            bandpath = lat.bandpath(path, npoints=npoints, density=density)
            return bandpath.transform(op)
        else:
            from ase.dft.kpoints import BandPath, resolve_custom_points
            path = resolve_custom_points(path, special_points, eps=eps)
            bandpath = BandPath(cell, path=path, special_points=special_points)
            return bandpath.interpolate(npoints=npoints, density=density)
Exemple #5
0
    def bandpath(self,
                 path=None,
                 npoints=None,
                 density=None,
                 special_points=None,
                 eps=2e-4):
        """Build a :class:`~ase.dft.kpoints.BandPath` for this cell.

        If special points are None, determine the Bravais lattice of
        this cell and return a suitable Brillouin zone path with
        standard special points.

        If special special points are given, interpolate the path
        directly from the available data.

        Parameters:

        path: string
            String of special point names defining the path, e.g. 'GXL'.
        npoints: int
            Number of points in total.  Note that at least one point
            is added for each special point in the path.
        density: float
            density of kpoints along the path in Å⁻¹.
        special_points: dict
            Dictionary mapping special points to scaled kpoint coordinates.
            For example ``{'G': [0, 0, 0], 'X': [1, 0, 0]}``.
        eps: float
            Tolerance for determining Bravais lattice.

        Example
        -------
        >>> cell = Cell.fromcellpar([4, 4, 4, 60, 60, 60])
        >>> cell.bandpath('GXW', npoints=20)
        BandPath(path='GXW', cell=[3x3], special_points={GKLUWX}, kpts=[20x3])

        """
        # TODO: Combine with the rotation transformation from bandpath()
        if special_points is None:
            from ase.lattice import identify_lattice
            lat, op = identify_lattice(self, eps=eps)
            path = lat.bandpath(path, npoints=npoints, density=density)
            return path.transform(op)
        else:
            from ase.dft.kpoints import BandPath, resolve_custom_points
            path = resolve_custom_points(path, special_points, eps=eps)
            path = BandPath(self, path=path, special_points=special_points)
            return path.interpolate(npoints=npoints, density=density)
def test_bad_shape():
    with pytest.raises(ValueError):
        resolve_custom_points([[np.zeros(2)]], {}, 0)
def test_autolabel_points_from_coords(kptcoords, special_points):
    path, dct = resolve_custom_points(kptcoords, {}, 0)
    assert path == 'Kpt0Kpt1'
    assert set(dct) == {'Kpt0', 'Kpt1'}  # automatically labelled
def test_recognize_points_from_coords(special_points):
    path, dct = resolve_custom_points(
        [[special_points['A'], special_points['B']]], special_points, 1e-5)
    assert path == 'AB'
    assert set(dct) == set('AB')
def test_str(special_points):
    path, dct = resolve_custom_points('AB', special_points, 0)
    assert path == 'AB'
    assert set(dct) == set('AB')
Exemple #10
0
    def add_to_plot(self, readoutfilesobj, label=None):
        """
        |Here you add individual plots that need to be plot and then just plot them with the plot() method
        |Use this method which is a part of the BandPlotterASE class you will have to give the bands to plot using a readoutfilesobj type of object
        """
        try:
            Ef = readoutfilesobj.atoms_objects[0].calc.get_fermi_level()
        except:
            print(f"add_to_plot: Could not read fermi level on scf file")
        try:
            kpts = readoutfilesobj.atoms_bands_objects[
                0].calc.get_ibz_k_points()
        except:
            print(f"add_to_plot: Could not read k points on bands file")

        if self.include_dos or self.plot_only_dos:
            if self.plot_from_QE_dos_file:
                E = []
                dos = []
                with open(readoutfilesobj.dos_file_name, "r") as dos_file:
                    for line in dos_file:
                        # print(line)
                        if "#" not in line:
                            data = line.strip().split()
                            E.append(float(data[0]) - Ef)
                            dos.append(float(data[1]))
                # self.y_to_plot.append(dos)
                # self.x_to_plot.append(E)
                self.dos.append(dos)
                self.E_dos.append(E)
                if self.plot_only_dos:  # Other wise we wil lappend to labels twice sicnce we will do it again at theloading of bands
                    self.labels.append(label)

            else:
                # we are here getting the required information for DOS
                # self.get_dos(readoutfilesobj)
                calc = readoutfilesobj.atoms_nscf_objects[0].calc
                Ef_nscf = readoutfilesobj.atoms_nscf_objects[
                    0].calc.get_fermi_level()
                dos = DOS(calc, width=0.2)
                self.dos.append(dos.get_dos())
                E_nscf = dos.get_energies()
                Ef_diff = Ef - Ef_nscf
                if abs(Ef_diff) >= 0.001:
                    print(
                        f"Warning!!! In {readoutfilesobj.identifier[0]}:\t|E_f_scf-E_f_nscf| = {abs(Ef_diff):.3} eV (>= 0.001 eV); E_f_scf = {Ef} eV,  E_f_nscf = {Ef_nscf} eV"
                    )
                if self.pin_fermi != "scf": self.E_dos.append(E_nscf)
                else: self.E_dos.append([E - Ef_diff for E in E_nscf])

        # Test space for k path and k high symmetry points
        # print(kpts)
        # print(self.plot_only_dos)
        if self.plot_only_dos == False:
            # This is for teh band structure
            path = readoutfilesobj.atoms_bands_objects[0].cell.bandpath(
                npoints=0)
            kinks = find_bandpath_kinks(
                readoutfilesobj.atoms_bands_objects[0].cell, kpts,
                eps=1e-5)  # These are the high symmetry points in use
            pathspec = resolve_custom_points(
                kpts[kinks], path.special_points, eps=1e-5
            )  # This gives the postions for the relevant high symmetry points
            # path.kpts = kpts
            # path.path = pathspec

            klengths = []
            for x in range(0, len(kpts)):
                if x == 0:
                    kdist = np.sqrt((0.0 - kpts[x][0])**2 +
                                    (0.0 - kpts[x][1])**2 +
                                    (0.0 - kpts[x][2])**2)
                    klengths.append(kdist)
                else:
                    kdist = np.sqrt((kpts[x - 1][0] - kpts[x][0])**2 +
                                    (kpts[x - 1][1] - kpts[x][1])**2 +
                                    (kpts[x - 1][2] - kpts[x][2])**2)
                    klengths.append(kdist + klengths[x - 1])

            self.k_locations = []
            for x in range(len(kinks)):
                self.k_locations.append(klengths[kinks[x]])

            self.k_symbols = []
            for x in pathspec:
                if x == "G":
                    self.k_symbols.append("$\Gamma$")
                else:
                    self.k_symbols.append(x)

            energies = []
            for s in range(readoutfilesobj.atoms_bands_objects[0].calc.
                           get_number_of_spins()):
                energies.append([
                    readoutfilesobj.atoms_bands_objects[0].calc.
                    get_eigenvalues(kpt=k, spin=s) for k in range(len(kpts))
                ])
            # print(f"lenght of kpoints: {range(len(kpts))}")
            Energy_to_plot = []
            if self.Ef_shift == True:
                for band in energies[0]:
                    if self.pin_fermi != "nscf":
                        Energy_to_plot.append([E - Ef for E in band])
                    else:
                        Energy_to_plot.append(
                            [E - Ef_nscf for E in band]
                        )  # here the assumption is that if this option is ever reached then the idea is that an nscf calculation has already being done and dos is being plotted.
            tempMain = []
            temp = []
            for x in range(len(Energy_to_plot[0])):
                for kpoint in Energy_to_plot:
                    temp.append(kpoint[x])
                tempMain.append(temp)
                temp = []
            self.y_to_plot.append(tempMain)
            self.x_to_plot.append(klengths)
            self.labels.append(label)