Esempio n. 1
0
    def _read_from_H(self, kgrid, kgrid_displ, Erange, nE, E0):
        """
        Calculates the PDOS from a sisl Hamiltonian.
        """
        if not hasattr(self, "H"):
            self.setup_hamiltonian()

        # Get the kgrid or generate a default grid by checking the interaction between cells
        # This should probably take into account how big the cell is.
        if kgrid is None:
            kgrid = [3 if nsc > 1 else 1 for nsc in self.H.geometry.nsc]

        if Erange is None:
            raise ValueError('You need to provide an energy range to calculate the PDOS from the Hamiltonian')

        self.E = np.linspace(Erange[0], Erange[-1], nE) + E0

        self.mp = sisl.MonkhorstPack(self.H, kgrid, kgrid_displ)

        # Define the available spins
        spin_indices = [0]
        if self.H.spin.is_polarized:
            spin_indices = [0, 1]

        # Calculate the PDOS for all available spins
        PDOS = []
        for spin in spin_indices:
            PDOS.append(self.mp.apply.average.PDOS(self.E, spin=spin, eta=True))
        self.PDOS = np.array(PDOS)
Esempio n. 2
0
def test_gf_write_read(sisl_tmp, sisl_system):
    tb = sisl.Hamiltonian(sisl_system.gtb)
    f = sisl_tmp('file.TSGF', _dir)

    bz = sisl.MonkhorstPack(tb, [3, 3, 1])
    E = np.linspace(-2, 2, 20) + 1j * 1e-4
    S = np.eye(len(tb), dtype=np.complex128)

    gf = sisl.io.get_sile(f)

    gf.write_header(E, bz, tb)
    for i, (write_hs, k, e) in enumerate(gf):
        Hk = tb.Hk(k, format='array')
        if write_hs and i % 2 == 0:
            gf.write_hamiltonian(Hk)
        elif write_hs:
            gf.write_hamiltonian(Hk, S)
        gf.write_self_energy(S * e - Hk)

    no_u, k, E_file = gf.read_header()
    assert np.allclose(E, E_file)
    assert np.allclose(k, bz.k)

    for i, (write_hs, k, e) in enumerate(gf):
        Hk = tb.Hk(k, format='array')
        if write_hs and i % 2 == 0:
            Hk_file, _ = gf.read_hamiltonian()
        elif write_hs:
            Hk_file, Sk_file = gf.read_hamiltonian()
            assert np.allclose(S, Sk_file)
        assert np.allclose(Hk, Hk_file)

        SE_file = gf.read_self_energy()
        assert np.allclose(SE_file, S * e - Hk)
Esempio n. 3
0
    def set_kmesh(self, nkpt=[1, 1, 1]):
        """ Set the k-mesh for the HubbardHamiltonian

        Parameters
        ----------
        nkpt : array_like or sisl.physics.BrillouinZone, optional
            k-mesh to be associated with the `hubbard.HubbardHamiltonian` instance
        """
        if isinstance(nkpt, sisl.BrillouinZone):
            self.mp = nkpt
        elif isinstance(nkpt, (np.ndarray, list)):
            self.mp = sisl.MonkhorstPack(self.H, nkpt)
        else:
            raise ValueError(self.__class__.__name__ + '.set_kmesh(...) requires an array_like input')
Esempio n. 4
0
def test_gf_write(sisl_tmp, sisl_system):
    tb = sisl.Hamiltonian(sisl_system.gtb)
    f = sisl_tmp('file.TSGF', _dir)
    gf = sisl.io.get_sile(f)
    bz = sisl.MonkhorstPack(tb, [3, 3, 1])
    E = np.linspace(-2, 2, 20) + 1j * 1e-4
    S = np.eye(len(tb), dtype=np.complex128)

    gf.write_header(E, bz, tb)
    for i, (write_hs, k, e) in enumerate(gf):
        Hk = tb.Hk(k, format='array')
        if write_hs and i % 2 == 0:
            gf.write_hamiltonian(Hk)
        elif write_hs:
            gf.write_hamiltonian(Hk, S)
        gf.write_self_energy(S * e - Hk)
Esempio n. 5
0
    def _read_from_H(self, kgrid, kgrid_displ, Erange, nE, E0, distribution):
        """
        Calculates the PDOS from a sisl Hamiltonian.
        """
        if not hasattr(self, "H"):
            self.setup_hamiltonian()

        if self.H is None:
            raise ValueError("No hamiltonian found.")

        # Get the kgrid or generate a default grid by checking the interaction between cells
        # This should probably take into account how big the cell is.
        if kgrid is None:
            kgrid = [3 if nsc > 1 else 1 for nsc in self.H.geometry.nsc]

        if Erange is None:
            raise ValueError(
                'You need to provide an energy range to calculate the PDOS from the Hamiltonian'
            )

        self.E = np.linspace(Erange[0], Erange[-1], nE) + E0

        self.bz = sisl.MonkhorstPack(self.H, kgrid, kgrid_displ)

        # Define the available spins
        spin_indices = [0]
        if self.H.spin.is_polarized:
            spin_indices = [0, 1]

        # Calculate the PDOS for all available spins
        PDOS = []
        for spin in spin_indices:
            with self.bz.apply(pool=_do_parallel_calc) as parallel:
                spin_PDOS = parallel.average.eigenstate(
                    spin=spin,
                    wrap=lambda eig: eig.PDOS(self.E,
                                              distribution=distribution))

            PDOS.append(spin_PDOS)

        if not self.H.spin.is_diagonal:
            PDOS = PDOS[0]

        self.PDOS = np.array(PDOS)
Esempio n. 6
0
def test_gf_write_read_spin(sisl_tmp, sisl_system):
    f = sisl_tmp('file.TSGF', _dir)

    tb = sisl.Hamiltonian(sisl_system.gtb, spin=sisl.Spin('P'))
    tb.construct([(0.1, 1.5), ([0.1, -0.1], [2.7, 1.6])])

    bz = sisl.MonkhorstPack(tb, [3, 3, 1])
    E = np.linspace(-2, 2, 3) + 1j * 1e-4
    S = np.eye(len(tb), dtype=np.complex128)

    gf = sisl.io.get_sile(f)

    gf.write_header(bz, E)
    for i, (ispin, write_hs, k, e) in enumerate(gf):
        Hk = tb.Hk(k, spin=ispin, format='array')
        if write_hs and i % 2 == 0:
            gf.write_hamiltonian(Hk)
        elif write_hs:
            gf.write_hamiltonian(Hk, S)
        gf.write_self_energy(S * e - Hk)

    # Check it isn't opened
    assert not gf._fortran_is_open()

    nspin, no_u, k, E_file = gf.read_header()
    assert nspin == 2
    assert np.allclose(E, E_file)
    assert np.allclose(k, bz.k)

    for i, (ispin, write_hs, k, e) in enumerate(gf):
        Hk = tb.Hk(k, spin=ispin, format='array')
        if write_hs and i % 2 == 0:
            Hk_file, _ = gf.read_hamiltonian()
        elif write_hs:
            Hk_file, Sk_file = gf.read_hamiltonian()
            assert np.allclose(S, Sk_file)
        assert np.allclose(Hk, Hk_file)

        SE_file = gf.read_self_energy()
        assert np.allclose(SE_file, S * e - Hk)
Esempio n. 7
0
def test_gf_write_read_direct(sisl_tmp, sisl_system):
    f = sisl_tmp('file.TSGF', _dir)

    tb = sisl.Hamiltonian(sisl_system.gtb, spin=sisl.Spin('P'))
    tb.construct([(0.1, 1.5), ([0.1, -0.1], [2.7, 1.6])])

    bz = sisl.MonkhorstPack(tb, [3, 3, 1])
    E = np.linspace(-2, 2, 3) + 1j * 1e-4
    S = np.eye(len(tb), dtype=np.complex128)

    gf = sisl.io.get_sile(f)

    gf.write_header(bz, E)
    for i, (ispin, write_hs, k, e) in enumerate(gf):
        Hk = tb.Hk(k, spin=ispin, format='array')
        if write_hs and i % 2 == 0:
            gf.write_hamiltonian(Hk)
        elif write_hs:
            gf.write_hamiltonian(Hk, S)
        gf.write_self_energy(S * e - Hk)

    # ensure it is not opened
    assert not gf._fortran_is_open()

    # First try from beginning
    for e in [0, 1, E[1], 0, E[0]]:
        ie = gf.Eindex(e)
        SE1 = gf.self_energy(e, bz.k[2, :])
        assert gf._state == 1
        assert gf._ik == 2
        assert gf._iE == ie
        assert gf._ispin == 0
        assert gf._is_read == 1

        SE2 = gf.self_energy(e, bz.k[2, :], spin=1)
        assert gf._state == 1
        assert gf._ik == 2
        assert gf._iE == ie
        assert gf._ispin == 1
        assert gf._is_read == 1

        assert not np.allclose(SE1, SE2)

        # In the middle we read some hamiltonians
        H1, S1 = gf.HkSk(bz.k[2, :], spin=0)
        assert gf._state == 0
        assert gf._ik == 2
        assert gf._iE == 0
        assert gf._ispin == 0
        assert gf._is_read == 1
        assert np.allclose(S, S1)

        H2, S1 = gf.HkSk(bz.k[2, :], spin=1)
        assert gf._state == 0
        assert gf._ik == 2
        assert gf._iE == 0
        assert gf._ispin == 1
        assert gf._is_read == 1
        assert np.allclose(S, S1)
        assert not np.allclose(H1, H2)
        assert not np.allclose(H1, SE1)

        H2, S1 = gf.HkSk(bz.k[2, :], spin=0)
        assert gf._state == 0
        assert gf._ik == 2
        assert gf._iE == 0
        assert gf._ispin == 0
        assert gf._is_read == 1
        assert np.allclose(S, S1)
        assert np.allclose(H1, H2)

        # Now read self-energy
        SE2 = gf.self_energy(e, bz.k[2, :], spin=0)
        assert gf._state == 1
        assert gf._ik == 2
        assert gf._iE == ie
        assert gf._ispin == 0
        assert gf._is_read == 1

        assert np.allclose(SE1, SE2)
Esempio n. 8
0
def run(
    bulk_hs,
    surface_hs,
    surface_tile,
    bulk_rsi_direction,
    mp_grid,
    energy_linspace,
    energy_imag,
    out_dir,
    k_axes,
    surf_nsc,
    bulk_nsc,
    matrix_fmt,
    zfp_tolerance,
    example_submit
):
    mprint("Reading hamiltonians")
    He = si.get_sile(bulk_hs).read_hamiltonian()
    Hs = si.get_sile(surface_hs).read_hamiltonian()

    if bulk_nsc is not None:
        He.set_nsc(bulk_nsc)
    if surf_nsc is not None:
        Hs.set_nsc(surf_nsc)

    with pick_a_rank() as r:
        mprint(f"Writing hamiltonians ({r})", printer=r)
        if rank == r:
            He.write(out_dir / "bulk_hamiltonian.nc")
            Hs.write(out_dir / "surface_hamiltonian.nc")

    rsi = si.physics.RecursiveSI(He, bulk_rsi_direction)
    rssi = si.physics.RealSpaceSI(rsi, Hs, k_axes, unfold=surface_tile)

    coupling_geom, se_indices = rssi.real_space_coupling(True)
    with pick_a_rank() as r:
        mprint(f"Saving coupling geometry ({r})", printer=r)
        if rank == r:
            coupling_geom.write(out_dir / "coupling_geometry.nc")
            np.save(out_dir / "coupling_geometry_indices", se_indices)

    parenths = rssi.real_space_parent()
    new_order = np.concatenate((se_indices, np.delete(np.arange(parenths.na), se_indices)))
    parenths = parenths.sub(new_order)
    with pick_a_rank() as r:
        mprint(f"Saving parent geometry ({r})", printer=r)
        if rank == r:
            parenths.geometry.write(out_dir / f"full_geometry.fdf")
            parenths.write(out_dir / f"full_geometry.nc")
    del parenths

    mp = np.array([1, 1, 1], dtype=int)
    mp[k_axes] = mp_grid
    rssi.set_options(bz=si.MonkhorstPack(coupling_geom, mp))

    E, dE = np.linspace(*energy_linspace[:2], int(energy_linspace[2]), retstep=True)
    nE = len(E)
    E = E + 1j*energy_imag
    with pick_a_rank() as r:
        mprint(f"Saving energy grid ({r})", printer=r)
        if rank == r:
            np.save(out_dir / "energy_grid", E)
            si.io.TableSile(out_dir / "energy_grid.table", "w").write_data(E.real, E.imag, np.full(E.shape, dE))

    nperrank = ceil(nE / comm.size)
    local_eidx = np.arange(rank * nperrank, min((rank + 1) * nperrank, nE))
    mprint("Energy grid distribution:", nperrank, "energy points per processor.")
    if (nE % nperrank):
        mprint(f"One process only has {nE % nperrank} energy points.")

    mprint(f"To assess processing progress, use `echo $(( 100 * $(find {out_dir} -type f -name 'SE_E*.npz' | wc -l) / {nE} ))%`")
    mprint(f"Note that these files due to the parallelism are probably created in bunches of {comm.size} and each bunch may take long to finish.")
    for ie, e in zip(local_eidx, E[local_eidx]):
        se = rssi.self_energy(e, bulk=True, coupling=True)
        mprint(f"SE{ie:>03d} calculated", printer=rank)
        if matrix_fmt == "npz":
            np.savez_compressed(out_dir / f"SE_E{ie:>03d}.npz", se)
        elif matrix_fmt == "zfp":
            bs = zfpy.compress_numpy(se.real, tolerance=zfp_tolerance)
            (out_dir / f"SE_E{ie:>03d}_REAL.zfp").write_bytes(bs)
            bs = zfpy.compress_numpy(se.imag, tolerance=zfp_tolerance)
            (out_dir / f"SE_E{ie:>03d}_IMAG.zfp").write_bytes(bs)
            del bs
        del se
        mprint(f"SE{ie:>03d} saved", printer=rank)
        gc.collect()
    mprint(f"MPI-rank {rank} done.", printer=rank)
    comm.Barrier()
    mprint((
        f"All done! Use `easySE gfdir2gf {out_dir}` to convert the parallel results"
        " into the tbtgf needed for Siesta/tbtrans."
    ))
Esempio n. 9
0
def add_levels(bz, nks, ns, fast=False, as_index=False, debug=False):
    """ Add different levels according to the length of `ns` """
    global nlvls

    lvl = nlvls - len(nks)
    nreps = 0

    if fast:
        # we need to copy the bz since for each ik, the new_bz gets
        # changed in add_levels.
        # If there was only 1 ik per level, then all would work fine.
        bz = bz.copy()

    from io import StringIO
    s = StringIO()

    def print_s(force=True):
        nonlocal s
        out = s.getvalue()
        spaces = " " * (lvl * 2)
        out = spaces + out.replace("\n", f"\n{spaces}")
        if force:
            print(out)

        # reset s
        s = StringIO()

    if debug:
        print(f"lvl = {lvl}", file=s)
        print_s()

    if len(nks) > 0:

        # calculate the size of the current BZ
        dsize = bz._size / bz._diag

        # pop the last items
        nk = get_nk(nks[-1])
        n = ns[-1]
        assert n < len(bz), "Too loong n"

        iks = [ik for ik in yield_kpoint(bz, n)]

        if debug:
            print("size", bz._size, file=s)
            print("dsize", dsize, file=s)
            print("iks", iks, file=s)
            print("len(bz): ", len(bz), file=s)
            print("ks:", file=s)
            print(bz.k[iks], file=s)
            print("weights:", bz.weight.min(), bz.weight[iks].sum(), file=s)
            print(bz.weight[iks], file=s)
            print("sum(weights): ", bz.weight.sum(), file=s)
            print_s()

        # create the single monkhorst pack we will use for replacements
        if fast:
            new_bz = sisl.MonkhorstPack(bz.parent, nk, size=dsize, trs=False)
            new, reps = add_levels(new_bz,
                                   nks[:-1],
                                   ns[:-1],
                                   fast,
                                   as_index,
                                   debug=debug)

            if as_index:
                bz.replace(iks, new, displacement=True, as_index=True)
            else:
                bz.replace(bz.k[iks], new, displacement=True, as_index=False)

            nreps += 1 + reps

        else:
            if lvl == 0:
                iks = tqdm(iks, desc=f"lvl {lvl}")
            for ik in iks:
                k = bz.k[ik]
                if debug:
                    print(f"ik = {ik}", file=s)
                    print(f"k = {k}", file=s)
                    print(f"wk = {bz.weight[ik]}", file=s)
                    print_s()

                # Recursively add a new level
                # create the single monkhorst pack we will use for replacements
                new_bz = sisl.MonkhorstPack(bz.parent,
                                            nk,
                                            size=dsize,
                                            trs=False,
                                            displacement=k)
                new, reps = add_levels(new_bz,
                                       nks[:-1],
                                       ns[:-1],
                                       fast,
                                       as_index,
                                       debug=debug)

                # calculate number of replaced k-points
                if debug:
                    bz_nk = len(bz)

                if debug:
                    print(f"ik = {ik}", file=s)
                    print(f"k = {k}", file=s)
                    print(f"wk = {bz.weight[ik]}", file=s)
                    print_s()

                if False:
                    import matplotlib.pyplot as plt
                    plt.figure()
                    plt.scatter(bz.k[:, 0], bz.k[:, 1])
                    plt.title(f"{lvl} and {ik}")
                    plt.show()

                if as_index:
                    bz.replace(ik, new, displacement=fast, as_index=True)
                else:
                    bz.replace(k, new, displacement=fast)

                if debug:
                    rep_nk = len(new) - (len(bz) - bz_nk)
                    print("replaced k-points ", rep_nk, file=s)
                    print_s()
                    #print(len(bz)*4 * 8 / 1024**3)

                del new

                nreps += 1 + reps
            del new_bz

    return bz, nreps
Esempio n. 10
0
                del new

                nreps += 1 + reps
            del new_bz

    return bz, nreps


gr = sisl.geom.graphene(1.44)
H = sisl.Hamiltonian(gr)
H.construct([[0, 1.44], [0, -2.7]])

# Now create the k-input
# this is number of k-points
trs = False
bz = sisl.MonkhorstPack(H, get_nk(nks[-1]), trs=trs)
debug = False

# Now add *many* points
for fast, as_index in [(True, False), (True, True), (False, False),
                       (False, True)]:
    # Always fix the random seed to make each profiling concurrent
    np.random.seed(1234567890)
    b = bz.copy()

    print(f"running fast={fast}  as_index={as_index}")
    pr = cProfile.Profile()
    pr.enable()
    _, nreps = add_levels(b, nks, ns, fast, as_index, debug=debug)
    pr.disable()