Ejemplo n.º 1
0
    def interpolate_ebands(self, vertices_names=None, line_density=20, ngkpt=None, shiftk=(0, 0, 0), kpoints=None):
        """
        Build new |ElectronBands| object by interpolating the KS Hamiltonian with Wannier functions.
        Supports k-path via (vertices_names, line_density), IBZ mesh defined by ngkpt and shiftk
        or input list of kpoints.

        Args:
            vertices_names: Used to specify the k-path for the interpolated QP band structure
                List of tuple, each tuple is of the form (kfrac_coords, kname) where
                kfrac_coords are the reduced coordinates of the k-point and kname is a string with the name of
                the k-point. Each point represents a vertex of the k-path. ``line_density`` defines
                the density of the sampling. If None, the k-path is automatically generated according
                to the point group of the system.
            line_density: Number of points in the smallest segment of the k-path. Used with ``vertices_names``.
            ngkpt: Mesh divisions. Used if bands should be interpolated in the IBZ.
            shiftk: Shifts for k-meshs. Used with ngkpt.
            kpoints: |KpointList| object taken e.g from a previous ElectronBands.
                Has precedence over vertices_names and line_density.

        Returns: |ElectronBands| object with Wannier-interpolated energies.
        """
        # Need KpointList object.
        if kpoints is None:
            if ngkpt is not None:
                # IBZ sampling
                kpoints = IrredZone.from_ngkpt(self.structure, ngkpt, shiftk, kptopt=1, verbose=0)
            else:
                # K-Path
                if vertices_names is None:
                    vertices_names = [(k.frac_coords, k.name) for k in self.structure.hsym_kpoints]
                kpoints = Kpath.from_vertices_and_names(self.structure, vertices_names, line_density=line_density)

        nk = len(kpoints)
        eigens = np.zeros((self.nsppol, nk, self.mwan))

        # Interpolate Hamiltonian for each kpoint and spin.
        start = time.time()
        write_warning = True
        for spin in range(self.nsppol):
            num_wan = self.nwan_spin[spin]
            for ik, kpt in enumerate(kpoints):
                oeigs = self.hwan.eval_sk(spin, kpt.frac_coords)
                eigens[spin, ik, :num_wan] = oeigs
                if num_wan < self.mwan:
                    # May have different number of wannier functions if nsppol == 2.
                    # Here I use the last value to fill eigens matrix (not very clean but oh well).
                    eigens[spin, ik, num_wan:self.mwan] = oeigs[-1]
                    if write_warning:
                        cprint("Different number of wannier functions for spin. Filling last bands with oeigs[-1]",
                               "yellow")
                        write_warning = False

        print("Interpolation completed in %.3f [s]" % (time.time() - start))
        occfacts = np.zeros_like(eigens)

        return ElectronBands(self.structure, kpoints, eigens, self.ebands.fermie,
                             occfacts, self.ebands.nelect, self.nspinor, self.nspden,
                             smearing=self.ebands.smearing)
Ejemplo n.º 2
0
    def get_interpolated_ebands_plotter(self, vertices_names=None, knames=None, line_density=20,
            ngkpt=None, shiftk=(0, 0, 0), kpoints=None, **kwargs):
        """
        Args:
            vertices_names: Used to specify the k-path for the interpolated QP band structure
                It's a list of tuple, each tuple is of the form (kfrac_coords, kname) where
                kfrac_coords are the reduced coordinates of the k-point and kname is a string with the name of
                the k-point. Each point represents a vertex of the k-path. ``line_density`` defines
                the density of the sampling. If None, the k-path is automatically generated according
                to the point group of the system.
            knames: List of strings with the k-point labels defining the k-path. It has precedence over `vertices_names`.
            line_density: Number of points in the smallest segment of the k-path. Used with ``vertices_names``.
            ngkpt: Mesh divisions. Used if bands should be interpolated in the IBZ.
            shiftk: Shifts for k-meshs. Used with ngkpt.
            kpoints: |KpointList| object taken e.g from a previous ElectronBands.
                Has precedence over vertices_names and line_density.

        Return: |ElectronBandsPlotter| object.
        """
        diff_str = self.has_different_structures()
        if diff_str: cprint(diff_str, "yellow")

        # Need KpointList object (assume same structures in Robot)
        nc0 = self.abifiles[0]
        if kpoints is None:
            if ngkpt is not None:
                # IBZ sampling
                kpoints = IrredZone.from_ngkpt(nc0.structure, ngkpt, shiftk, kptopt=1, verbose=0)
            else:
                # K-Path
                if knames is not None:
                    kpoints = Kpath.from_names(nc0.structure, knames, line_density=line_density)
                else:
                    if vertices_names is None:
                        vertices_names = [(k.frac_coords, k.name) for k in nc0.structure.hsym_kpoints]
                    kpoints = Kpath.from_vertices_and_names(nc0.structure, vertices_names, line_density=line_density)

        plotter = ElectronBandsPlotter()
        for label, abiwan in self.items():
            plotter.add_ebands(label, abiwan.interpolate_ebands(kpoints=kpoints))

        return plotter
Ejemplo n.º 3
0
    def test_kpath_api(self):
        """Testing Kpath API."""
        structure = abilab.Structure.as_structure(abidata.cif_file("si.cif"))

        knames = ["G", "X", "L", "G"]
        kpath = Kpath.from_names(structure, knames, line_density=5)
        repr(kpath); str(kpath)
        assert kpath.to_string(verbose=2, title="Kpath")
        assert not kpath.is_ibz and kpath.is_path
        assert kpath[0].is_gamma and kpath[-1].is_gamma
        #assert len(kpath.ds) == len(self) - 1
        #assert kpath.ksampling.kptopt == 1
        #self.assert_equal(kpath.ksampling.mpdivs, [4, 4, 4])

        assert len(kpath.ds) == len(kpath) - 1
        assert len(kpath.versors) == len(kpath) - 1
        assert len(kpath.lines) == len(knames) - 1
        self.assert_almost_equal(kpath.frac_bounds, structure.get_kcoords_from_names(knames))
        self.assert_almost_equal(kpath.cart_bounds, structure.get_kcoords_from_names(knames, cart_coords=True))

        r = kpath.find_points_along_path(kpath.get_cart_coords())
        assert len(r.ikfound) == len(kpath)
        self.assert_equal(r.ikfound,
            [ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0])
Ejemplo n.º 4
0
    def interpolate_ebands(self,
                           vertices_names=None,
                           line_density=20,
                           ngkpt=None,
                           shiftk=(0, 0, 0),
                           kpoints=None):
        """
        Build new |ElectronBands| object by interpolating the KS Hamiltonian with Wannier functions.
        Supports k-path via (vertices_names, line_density), IBZ mesh defined by ngkpt and shiftk
        or input list of kpoints.

        Args:
            vertices_names: Used to specify the k-path for the interpolated QP band structure
                List of tuple, each tuple is of the form (kfrac_coords, kname) where
                kfrac_coords are the reduced coordinates of the k-point and kname is a string with the name of
                the k-point. Each point represents a vertex of the k-path. ``line_density`` defines
                the density of the sampling. If None, the k-path is automatically generated according
                to the point group of the system.
            line_density: Number of points in the smallest segment of the k-path. Used with ``vertices_names``.
            ngkpt: Mesh divisions. Used if bands should be interpolated in the IBZ.
            shiftk: Shifts for k-meshs. Used with ngkpt.
            kpoints: |KpointList| object taken e.g from a previous ElectronBands.
                Has precedence over vertices_names and line_density.

        Returns: |ElectronBands| object with Wannier-interpolated energies.
        """
        # Need KpointList object.
        if kpoints is None:
            if ngkpt is not None:
                # IBZ sampling
                kpoints = IrredZone.from_ngkpt(self.structure,
                                               ngkpt,
                                               shiftk,
                                               kptopt=1,
                                               verbose=0)
            else:
                # K-Path
                if vertices_names is None:
                    vertices_names = [(k.frac_coords, k.name)
                                      for k in self.structure.hsym_kpoints]
                kpoints = Kpath.from_vertices_and_names(
                    self.structure, vertices_names, line_density=line_density)

        nk = len(kpoints)
        eigens = np.zeros((self.nsppol, nk, self.mwan))

        # Interpolate Hamiltonian for each kpoint and spin.
        start = time.time()
        write_warning = True
        for spin in range(self.nsppol):
            num_wan = self.nwan_spin[spin]
            for ik, kpt in enumerate(kpoints):
                oeigs = self.hwan.eval_sk(spin, kpt.frac_coords)
                eigens[spin, ik, :num_wan] = oeigs
                if num_wan < self.mwan:
                    # May have different number of wannier functions if nsppol == 2.
                    # Here I use the last value to fill eigens matrix (not very clean but oh well).
                    eigens[spin, ik, num_wan:self.mwan] = oeigs[-1]
                    if write_warning:
                        cprint(
                            "Different number of wannier functions for spin. Filling last bands with oeigs[-1]",
                            "yellow")
                        write_warning = False

        print("Interpolation completed in %.3f [s]" % (time.time() - start))
        occfacts = np.zeros_like(eigens)

        return ElectronBands(self.structure,
                             kpoints,
                             eigens,
                             self.ebands.fermie,
                             occfacts,
                             self.ebands.nelect,
                             self.nspinor,
                             self.nspden,
                             smearing=self.ebands.smearing)
Ejemplo n.º 5
0
 def qpoints(self):
     """List of Q-points."""
     frac_coords = self.reader.read_value('qpoints')
     return Kpath(self.structure.reciprocal_lattice,
                  frac_coords,
                  ksampling=None)
Ejemplo n.º 6
0
    def test_kpath_api(self):
        """Testing Kpath API."""
        structure = abilab.Structure.as_structure(abidata.cif_file("si.cif"))

        knames = ["G", "X", "L", "G"]
        kpath = Kpath.from_names(structure, knames, line_density=5)
        repr(kpath)
        str(kpath)
        assert kpath.to_string(verbose=2, title="Kpath")
        assert not kpath.is_ibz and kpath.is_path
        assert kpath[0].is_gamma and kpath[-1].is_gamma
        #assert len(kpath.ds) == len(self) - 1
        #assert kpath.ksampling.kptopt == 1
        #self.assert_equal(kpath.ksampling.mpdivs, [4, 4, 4])

        assert len(kpath.ds) == len(kpath) - 1
        assert len(kpath.versors) == len(kpath) - 1
        assert len(kpath.lines) == len(knames) - 1
        self.assert_almost_equal(kpath.frac_bounds,
                                 structure.get_kcoords_from_names(knames))
        self.assert_almost_equal(
            kpath.cart_bounds,
            structure.get_kcoords_from_names(knames, cart_coords=True))

        r = kpath.find_points_along_path(kpath.get_cart_coords())
        assert len(r.ikfound) == len(kpath)
        self.assert_equal(
            r.ikfound,
            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0])

        #kpath = IrredZone.from_kppa(structure, kppa=1000, shiftk=[0.5, 0.5, 0.5], kptopt=1, verbose=1)
        #assert not kpath.is_ibz and kpath.is_path
        #assert len(kpath) == 60
        #self.assert_equal(kpath.ksampling.mpdivs, [8, 8, 8])

        segments = build_segments(
            k0_list=(0, 0, 0),
            npts=1,
            step=0.01,
            red_dirs=(1, 0, 0),
            reciprocal_lattice=structure.reciprocal_lattice)
        assert len(segments) == 1
        assert np.all(segments[0] == (0, 0, 0))

        step, npts = 0.1, 5
        red_dir = np.array((1, 1, 0))
        segments = build_segments(
            k0_list=(0, 0, 0, 0.5, 0, 0),
            npts=npts,
            step=step,
            red_dirs=red_dir,
            reciprocal_lattice=structure.reciprocal_lattice)

        #print("segments:\n", segments)
        # (nk0_list, len(red_dirs) * npts, 3)
        assert segments.shape == (2, npts, 3)
        self.assert_almost_equal(segments[0, 2], (0, 0, 0))
        self.assert_almost_equal(segments[1, 2], (0.5, 0.0, 0))

        def r2c(vec):
            return structure.reciprocal_lattice.get_cartesian_coords(vec)

        cart_vers = r2c(red_dir)
        cart_vers /= np.linalg.norm(cart_vers)
        self.assert_almost_equal(r2c(segments[1, 1] - segments[1, 0]),
                                 step * cart_vers)
        self.assert_almost_equal(r2c(segments[1, 3] - segments[1, 2]),
                                 step * cart_vers)