Exemplo n.º 1
0
    def get_continuous_path(bandstructure):
        """
        Obtain a continous version of an inputted path using graph theory.
        This routine will attempt to add connections between nodes of
        odd-degree to ensure a Eulerian path can be formed. Initial
        k-path must be able to be converted to a connected graph. See
        npj Comput Mater 6, 112 (2020). 10.1038/s41524-020-00383-7
        for more details.

        Args:
        bandstructure (BandstructureSymmLine): BandstructureSymmLine object.

        Returns:
        bandstructure (BandstructureSymmLine): New BandstructureSymmLine object with continous path.
        """

        G = nx.Graph()

        labels = []
        for point in bandstructure.kpoints:
            if point.label is not None:
                labels.append(point.label)

        plot_axis = []
        for i in range(int(len(labels) / 2)):
            G.add_edges_from([(labels[2 * i], labels[(2 * i) + 1])])
            plot_axis.append((labels[2 * i], labels[(2 * i) + 1]))

        G_euler = nx.algorithms.euler.eulerize(G)

        G_euler_circuit = nx.algorithms.euler.eulerian_circuit(G_euler)

        distances_map = []
        kpath_euler = []

        for edge_euler in G_euler_circuit:
            kpath_euler.append(edge_euler)
            for edge_reg in plot_axis:
                if edge_euler == edge_reg:
                    distances_map.append((plot_axis.index(edge_reg), False))
                elif edge_euler[::-1] == edge_reg:
                    distances_map.append((plot_axis.index(edge_reg), True))

        if bandstructure.is_spin_polarized:
            spins = [Spin.up, Spin.down]
        else:
            spins = [Spin.up]

        new_kpoints = []
        new_bands = {
            spin: [np.array([]) for _ in range(bandstructure.nb_bands)]
            for spin in spins
        }
        new_projections = {
            spin: [[] for _ in range(bandstructure.nb_bands)]
            for spin in spins
        }

        for entry in distances_map:
            if not entry[1]:
                branch = bandstructure.branches[entry[0]]
                start = branch["start_index"]
                stop = branch["end_index"] + 1
                step = 1

            else:
                branch = bandstructure.branches[entry[0]]
                start = branch["end_index"]
                stop = branch["start_index"] - 1
                step = -1

            # kpoints
            new_kpoints += [
                point.frac_coords
                for point in bandstructure.kpoints[start:stop:step]
            ]

            # eigenvals
            for spin in spins:
                for n, band in enumerate(bandstructure.bands[spin]):

                    new_bands[spin][n] = np.concatenate(
                        (new_bands[spin][n], band[start:stop:step]))

            # projections
            for spin in spins:
                for n, band in enumerate(bandstructure.projections[spin]):

                    new_projections[spin][n] += band[start:stop:step].tolist()

        for spin in spins:
            new_projections[spin] = np.array(new_projections[spin])

        new_labels_dict = {
            label: point.frac_coords
            for label, point in bandstructure.labels_dict.items()
        }

        new_bandstructure = BandStructureSymmLine(
            kpoints=new_kpoints,
            eigenvals=new_bands,
            lattice=bandstructure.lattice_rec,
            efermi=bandstructure.efermi,
            labels_dict=new_labels_dict,
            structure=bandstructure.structure,
            projections=new_projections,
        )

        return new_bandstructure
Exemplo n.º 2
0
    def get_line_mode_band_structure(
        self,
        line_density: int = 50,
        kpath: Optional[Kpath] = None,
        energy_cutoff: Optional[float] = None,
        scissor: Optional[float] = None,
        bandgap: Optional[float] = None,
        symprec: Optional[float] = defaults["symprec"],
        return_other_properties: bool = False,
    ) -> Union[
        BandStructureSymmLine,
        Tuple[BandStructureSymmLine, Dict[Spin, Dict[str, np.ndarray]]],
    ]:
        """Gets the interpolated band structure along high symmetry directions.

        Args:
            line_density: The maximum number of k-points between each two
                consecutive high-symmetry k-points
            energy_cutoff: The energy cut-off to determine which bands are
                included in the interpolation. If the energy of a band falls
                within the cut-off at any k-point it will be included. For
                metals the range is defined as the Fermi level ± energy_cutoff.
                For gapped materials, the energy range is from the VBM -
                energy_cutoff to the CBM + energy_cutoff.
            scissor: The amount by which the band gap is scissored. Cannot
                be used in conjunction with the ``bandgap`` option. Has no
                effect for metallic systems.
            bandgap: Automatically adjust the band gap to this value. Cannot
                be used in conjunction with the ``scissor`` option. Has no
                effect for metallic systems.
            symprec: The symmetry tolerance used to determine the space group
                and high-symmetry path.
            return_other_properties: Whether to include the interpolated
                other_properties data for each k-point along the band structure path.

        Returns:
            The line mode band structure.
        """
        if not kpath:
            kpath = PymatgenKpath(self._band_structure.structure, symprec=symprec)

        kpoints, labels = kpath.get_kpoints(line_density=line_density, cart_coords=True)
        labels_dict = {
            label: kpoint for kpoint, label in zip(kpoints, labels) if label != ""
        }

        energies = self.get_energies(
            kpoints,
            scissor=scissor,
            bandgap=bandgap,
            atomic_units=False,
            energy_cutoff=energy_cutoff,
            coords_are_cartesian=True,
            return_other_properties=return_other_properties,
            symprec=symprec,
        )

        if return_other_properties:
            energies, other_properties = energies

        bs = BandStructureSymmLine(
            kpoints,
            energies,
            self._band_structure.structure.lattice,
            self._band_structure.efermi,
            labels_dict,
            coords_are_cartesian=True,
        )

        if return_other_properties:
            return bs, other_properties
        else:
            return bs