Example #1
0
def compute_self_energies_for_leads(energy, h_l, h_0, h_r, save=True):
    sgf_l = []
    sgf_r = []
    factor = []
    factor1 = []
    factor2 = []

    num_sites = h_0.shape[0]

    for j, E in enumerate(energy):
        L, R = tb.surface_greens_function(E, h_l, h_0, h_r, iterate=3)

        test_gf = E * np.identity(num_sites) - h_0 - L - R
        metrics = np.linalg.cond(test_gf)
        print("{} of {}: energy is {}, metrics is {}".format(
            j + 1, energy.shape[0], E, metrics))

        # if metrics > 15000:
        #     R = iterate_gf(E, h_0, h_l, h_r, R, 1)
        #     L = iterate_gf(E, h_0, h_l, h_r, L, 1)

        sgf_l.append(L)
        sgf_r.append(R)

    sgf_l = np.array(sgf_l)
    sgf_r = np.array(sgf_r)

    if save:
        np.save('sgf_l', sgf_l)
        np.save('sgf_r', sgf_r)

    return sgf_l, sgf_r
Example #2
0
def test_main():
    import sys
    sys.path.insert(0, '/home/mk/TB_project/tb')
    import tb

    a = tb.Atom('A')
    a.add_orbital('s', -0.7)

    tb.Atom.orbital_sets = {'A': a}

    tb.set_tb_params(PARAMS_A_A={'ss_sigma': -0.5},
                     PARAMS_B_B={'ss_sigma': -0.5},
                     PARAMS_A_B={'ss_sigma': -0.5},
                     PARAMS_B_C={'ss_sigma': -0.5},
                     PARAMS_A_C={'ss_sigma': -0.5})

    xyz_file = """1
    H cell
    A1       0.0000000000    0.0000000000    0.0000000000                                                                                                      
    """

    h = tb.Hamiltonian(xyz=xyz_file, nn_distance=2.1)
    h.initialize()
    h.set_periodic_bc([[0, 0, 1.0]])
    h_l, h_0, h_r = h.get_coupling_hamiltonians()

    energy = np.linspace(-3.0, 1.5, 700)

    sgf_l = []
    sgf_r = []

    for E in energy:
        L, R = tb.surface_greens_function(E, h_l, h_0, h_r)
        # L, R = surface_greens_function_poles_Shur(E, h_l, h_0, h_r)
        sgf_l.append(L)
        sgf_r.append(R)

    sgf_l = np.array(sgf_l)
    sgf_r = np.array(sgf_r)

    num_sites = h_0.shape[0]
    gf = np.linalg.pinv(
        np.multiply.outer(energy, np.identity(num_sites)) - h_0 - sgf_l -
        sgf_r)

    dos = -np.trace(np.imag(gf), axis1=1, axis2=2)

    tr = np.zeros((energy.shape[0]), dtype=np.complex)

    for j, E in enumerate(energy):
        gf0 = np.matrix(gf[j, :, :])
        gamma_l = 1j * (np.matrix(sgf_l[j, :, :]) -
                        np.matrix(sgf_l[j, :, :]).H)
        gamma_r = 1j * (np.matrix(sgf_r[j, :, :]) -
                        np.matrix(sgf_r[j, :, :]).H)
        tr[j] = np.real(np.trace(gamma_l * gf0 * gamma_r * gf0.H))
        dos[j] = np.real(np.trace(1j * (gf0 - gf0.H)))
Example #3
0
def single_atom_chain():
    """
    Test set for a single-atom chain.

    :return:
    """

    sys.path.insert(0, '/home/mk/TB_project/tb')

    a = tb.Atom('A')
    a.add_orbital('s', 0.7)
    tb.Atom.orbital_sets = {'A': a}
    tb.set_tb_params(PARAMS_A_A={'ss_sigma': 0.5})

    xyz_file = """1
    H cell
    A1       0.0000000000    0.0000000000    0.0000000000
    """

    h = tb.Hamiltonian(xyz=xyz_file, nn_distance=1.1)
    h.initialize()
    h.set_periodic_bc([[0, 0, 1.0]])
    h_l, h_0, h_r = h.get_coupling_hamiltonians()
    num_sites = h_0.shape[0]

    energy = np.linspace(-3.0, 3.0, 300)

    tr = np.zeros((energy.shape[0]))
    dos = np.zeros((energy.shape[0]))

    sgf_l = []
    sgf_r = []

    for j, E in enumerate(energy):
        se_l, se_r = tb.surface_greens_function(E, h_l, h_0, h_r)
        sgf_l.append(se_l)
        sgf_r.append(se_r)
        gf = np.linalg.pinv(E * np.identity(num_sites) - h_0 - se_l - se_r)
        gf = np.matrix(gf)
        gamma_l = 1j * (np.matrix(se_l) - np.matrix(se_l).H)
        gamma_r = 1j * (np.matrix(se_r) - np.matrix(se_r).H)
        tr[j] = np.real(np.trace(gamma_l * gf * gamma_r * gf.H))
        dos[j] = np.real(np.trace(1j * (gf - gf.H)))

    sgf_l = np.array(sgf_l)
    sgf_r = np.array(sgf_r)

    return energy, dos, tr, h, sgf_l, sgf_r
Example #4
0
    def main(param_file, energy, show, save):

        params = tb.yaml_parser(param_file)
        hamiltonian = tb.initializer(**params)
        h_l, h_0, h_r = hamiltonian.get_coupling_hamiltonians()

        sgf_l = []
        sgf_r = []

        for E in energy:
            L, R = tb.surface_greens_function(E, h_l, h_0, h_r)
            sgf_l.append(L)
            sgf_r.append(R)

        sgf_l = np.array(sgf_l)
        sgf_r = np.array(sgf_r)

        num_sites = h_0.shape[0]
        gf = np.linalg.pinv(
            np.multiply.outer(energy, np.identity(num_sites)) - h_0 - sgf_l -
            sgf_r)

        dos = -np.trace(np.imag(gf), axis1=1, axis2=2)

        tr = np.zeros((energy.shape[0]), dtype=np.complex)

        for j, E in enumerate(energy):
            gf0 = np.matrix(gf[j, :, :])
            gamma_l = 1j * (np.matrix(sgf_l[j, :, :]) -
                            np.matrix(sgf_l[j, :, :]).H)
            gamma_r = 1j * (np.matrix(sgf_r[j, :, :]) -
                            np.matrix(sgf_r[j, :, :]).H)
            tr[j] = np.real(np.trace(gamma_l * gf0 * gamma_r * gf0.H))
            dos[j] = np.real(np.trace(1j * (gf0 - gf0.H)))

        if show:
            axes = plt.axes()
            axes.set_title('Band structure')
            axes.set_xlabel('Wave vectors')
            axes.set_ylabel('Energy (eV)')
            axes.plot(dos)
            plt.show()

        if save:
            pass
def test_gf_single_atom_chain():
    sys.path.insert(0, '/home/mk/TB_project/tb')

    a = tb.Atom('A')
    a.add_orbital('s', 0.7)
    tb.Atom.orbital_sets = {'A': a}
    tb.set_tb_params(PARAMS_A_A={'ss_sigma': 0.5})

    xyz_file = """1
    H cell
    A1       0.0000000000    0.0000000000    0.0000000000
    """

    h = tb.Hamiltonian(xyz=xyz_file, nn_distance=1.1)
    h.initialize()
    h.set_periodic_bc([[0, 0, 1.0]])
    h_l, h_0, h_r = h.get_coupling_hamiltonians()

    energy = np.linspace(-3.0, 3.0, 300)

    sgf_l = []
    sgf_r = []

    for E in energy:
        L, R = tb.surface_greens_function(E, h_l, h_0, h_r)
        sgf_l.append(L)
        sgf_r.append(R)

    sgf_l = np.array(sgf_l)
    sgf_r = np.array(sgf_r)

    num_sites = h_0.shape[0]
    gf = np.linalg.pinv(
        np.multiply.outer(energy, np.identity(num_sites)) - h_0 - sgf_l -
        sgf_r)

    np.testing.assert_allclose(sgf_l, sgf_r, atol=1e-5)
    expected = h_l * simple_chain_greens_function(energy, h_0, h_r) * h_r
    np.testing.assert_allclose(np.squeeze(sgf_r),
                               np.squeeze(expected),
                               atol=1e-5)
Example #6
0
def compute_self_energies_for_leads(energy, h_l, h_0, h_r, save=None):
    sgf_l = []
    sgf_r = []
    num_sites = h_0.shape[0]

    for j, E in enumerate(energy):
        L, R = tb.surface_greens_function(E, h_l, h_0, h_r, iterate=True)

        test_gf = E * np.identity(num_sites) - h_0 - L - R
        metrics = np.linalg.cond(test_gf)
        print("{} of {}: energy is {}, metrics is {}".format(j + 1, energy.shape[0], E, metrics))

        sgf_l.append(L)
        sgf_r.append(R)

    sgf_l = np.array(sgf_l)
    sgf_r = np.array(sgf_r)

    if save:
        np.save(os.path.join(save, 'sgf_l'), sgf_l)
        np.save(os.path.join(save, 'sgf_r'), sgf_r)
        np.save(os.path.join(save, 'energy'), energy)

    return sgf_l, sgf_r
Example #7
0
def main1(job_title, nw_path, fields_config, negf_config, comm=0, reduced_modes=False, save=True):
    if comm:
        rank = comm.Get_rank()
        size = comm.Get_size()
    else:
        rank = 0
        size = 1

    params = yaml_parser(fields_config)
    negf_params = yaml_parser(negf_config)

    # ---------------------------------------------------------------------------------
    # ------------compute tight-binding matrices and define energy scale --------------
    # ---------------------------------------------------------------------------------

    h_l, h_0, h_r, coords, path = compute_tb_matrices(input_file=nw_path)

    energy = np.linspace(negf_params['energy']['start'],
                         negf_params['energy']['end'],
                         negf_params['energy']['steps'])

    if reduced_modes:
        ref_energy = np.linspace(negf_params['basis'][0],
                                 negf_params['basis'][1],
                                 negf_params['basis'][2])
        h_ls, h_0s, h_rs, _, new_basis = tb.reduce_mode_space(ref_energy,
                                                              h_l, h_0, h_r,
                                                              0.1,
                                                              input_file=nw_path)
    else:
        h_ls = h_l
        h_0s = h_0
        h_rs = h_r
        new_basis = []

    # ---------------------------------------------------------------------------------
    # ------- pre-compute/pre-load self-energies for the leads from the disk ----------
    # ---------------------------------------------------------------------------------

    # sgf_l, sgf_r = compute_self_energies_for_leads(energy, h_l, h_0, h_r, save='./SiNW/SiNW2/')
    # sgf_l = np.load('sgf_l.npy')
    # sgf_r = np.load('sgf_r.npy')

    # ---------------------------------------------------------------------------------
    # ---------------------------- make a chain Hamiltonian ---------------------------
    # ---------------------------------------------------------------------------------

    h_0 = h_0 + 1j * negf_params['dephasing'] * np.identity(h_0.shape[0])

    h_chain = HamiltonianChainComposer(h_l, h_0, h_r, coords, params)

    # visualize1(h_chain, h_chain.dict_of_fields['cation'], -0.85, -0.85, -18.7, eps=3.8)

    # h_chain.visualize()

    if len(new_basis) > 0:
        for j, item in enumerate(h_chain.h_0):
            h_chain.h_0[j] = new_basis.H * item * new_basis

        for j, item in enumerate(h_chain.h_l):
            h_chain.h_l[j] = new_basis.H * item * new_basis

        for j, item in enumerate(h_chain.h_r):
            h_chain.h_r[j] = new_basis.H * item * new_basis

    # ---------------------------------------------------------------------------------
    # -------------------- compute Green's functions of the system --------------------
    # ---------------------------------------------------------------------------------

    num_periods = params['left_translations'] + params['right_translations'] + 1

    dos = np.zeros((energy.shape[0]))
    tr = np.zeros((energy.shape[0]))
    # dens = np.zeros((energy.shape[0], len(h_chain.z_coords())))
    dens = np.zeros((energy.shape[0], num_periods))

    par_data = []

    ef1 = negf_params['ef1']
    ef2 = negf_params['ef2']
    tempr = negf_params['tempr']

    for j, E in enumerate(energy):
        if j % size != rank:
            continue

        L, R = tb.surface_greens_function(E, h_ls, h_0s, h_rs, iterate=5)

        # L = L + se(E, 2.0, 2.125, negf_params['dephasing'])
        # R = R + se(E, 2.0, 2.125, negf_params['dephasing'])

        h_chain.add_self_energies(L, R, energy=E, tempr=tempr, ef1=ef1, ef2=ef2)
        g_trans, grd, grl, gru, gr_left, gnd, gnl, gnu, gn_left = recursive_gf(E,
                                                                               h_chain.h_l,
                                                                               h_chain.h_0,
                                                                               h_chain.h_r,
                                                                               s_in=h_chain.sgf)
        h_chain.remove_self_energies()

        for jj in range(num_periods):
            dos[j] = dos[j] + np.real(np.trace(1j * (grd[jj] - grd[jj].H))) / num_periods
            dens[j, jj] = dens[j, jj] + 2 * np.trace(gnd[jj])

            # for jj1 in range(gnd[jj].shape[0]):
            #
            #     dens[j, h_chain.z_coords_map(jj * gnd[jj].shape[0] + jj1)] = \
            #         dens[j, h_chain.z_coords_map(jj * gnd[jj].shape[0] + jj1)] + 2 * gnd[jj][jj1, jj1]

        gamma_l = 1j * (np.matrix(L) - np.matrix(L).H)
        gamma_r = 1j * (np.matrix(R) - np.matrix(R).H)
        tr[j] = np.real(np.trace(gamma_r * g_trans * gamma_l * g_trans.H))

        print("{} of {}: energy is {}".format(j + 1, energy.shape[0], E))

        if comm:
            par_data.append({'id': j, 'dos': dos[j], 'tr': tr[j], 'dens': dens[j, :]})

    if comm:

        par_data = comm.reduce(par_data, root=0)

        if rank == 0:
            ids = [par_data[item]['id'] for item in range(len(par_data))]
            dos = [x['dos'] for _, x in sorted(zip(ids, par_data))]
            tr = [x['tr'] for _, x in sorted(zip(ids, par_data))]
            dens = [x['dens'] for _, x in sorted(zip(ids, par_data))]
            dos = np.array(dos)
            tr = np.array(tr)
            dens = np.array(dens)

            if save:
                np.save(os.path.join(nw_path, 'dos' + job_title + '.npy'), dos)
                np.save(os.path.join(nw_path, 'tr' + job_title + '.npy'), tr)
                np.save(os.path.join(nw_path, 'dens' + job_title + '.npy'), dens)
                np.save(os.path.join(nw_path, 'energy.npy'), energy)

            return dos, tr, dens

    else:

        # for j in range(1, dens.shape[1]):
        #     if np.sum(dens[:, j]) < 0.5:
        #         dens[:, j] = dens[:, j-1]

        # for j in range(1, dens.shape[0]):
        #     dens[j, :] = np.convolve(dens[j, :], np.ones((3,)) / 3, mode='valid')

        if save:
            np.save(os.path.join(nw_path, 'dos' + job_title + '.npy'), dos)
            np.save(os.path.join(nw_path, 'tr' + job_title + '.npy'), tr)
            np.save(os.path.join(nw_path, 'dens' + job_title + '.npy'), dens)
            np.save(os.path.join(nw_path, 'energy.npy'), energy)

        return dos, tr, dens
Example #8
0
def main(spacing, mol_path, nw_path, eps, comm=0):
    if comm:
        rank = comm.Get_rank()
        size = comm.Get_size()
    else:
        rank = 0
        size = 1

    # ---------------------------------------------------------------------------------
    # ----------- compute tight-binding matrices and define energy scale --------------
    # ---------------------------------------------------------------------------------

    h_l, h_0, h_r, coords, path = compute_tb_matrices(input_file=nw_path)
    energy = np.linspace(2.1, 2.15, 50)
    energy = energy[15:30]

    # ---------------------------------------------------------------------------------
    # ------- pre-compute/pre-load self-energies for the leads from the disk ----------
    # ---------------------------------------------------------------------------------

    # sgf_l, sgf_r = compute_self_energies_for_leads(energy, h_l, h_0, h_r, save='./SiNW/SiNW2/')
    # sgf_l = np.load('sgf_l.npy')
    # sgf_r = np.load('sgf_r.npy')

    # ---------------------------------------------------------------------------------
    # ---------------------------- make a chain Hamiltonian ---------------------------
    # ---------------------------------------------------------------------------------

    num_periods = 3  # number of unit cells in the device region num_periods * 2 + 1

    h_chain = HamiltonianChain(h_l, h_0, h_r, coords)
    h_chain.translate([[0, 0, 5.50]], num_periods, num_periods)

    # ---------------------------------------------------------------------------------
    # --------------------- make a Field object from the cube file --------------------
    # ---------------------------------------------------------------------------------

    field = Field(path=mol_path)

    angle = 1.13446  # 65 degrees
    field.rotate('x', angle)
    field.rotate('y', np.pi / 2.0)

    # field.set_origin(np.array([6.36, 11.86, 2.75]))
    # field.set_origin(np.array([-11.82 - 11.5, 0.0, 5.91]))

    size_x_min = np.min(coords[:, 0])
    size_x_max = np.max(coords[:, 0])
    size_y_min = np.min(coords[:, 1])
    size_y_max = np.max(coords[:, 1])
    size_z_min = -np.max(coords[:, 2]) * 4
    size_z_max = np.max(coords[:, 2]) * 3

    _, mol_coords = field.get_atoms()
    mol_y_length0 = np.max(mol_coords[:, 1]) - np.min(mol_coords[:, 1])
    mol_y_length = mol_y_length0 * np.sin(angle)
    mol_z_length = mol_y_length0 * np.cos(angle)

    field.set_origin(np.array([0.5 * (size_x_max - np.abs(size_y_min)),
                               size_y_max + 0.5 * mol_y_length + spacing,
                               0.5 * mol_z_length]))

    # ---------------------------------------------------------------------------------
    # ------------------- add field to the Hamiltonian and visualize ------------------
    # ---------------------------------------------------------------------------------

    field1 = deepcopy(field)
    field1.add_screening(eps, mol_y_length0, spacing)
    visualize2(h_chain, [field1, field], size_x_min, size_y_min, size_z_min, eps=[1.0, 3.8])

    h_chain1 = deepcopy(h_chain)

    h_chain.add_field(field, eps=3.8)
    h_chain1.add_field(field1, eps=1.0)

    # if isinstance(eps, list):
    #     field.add_screening(eps, mol_y_length0)
    #     h_chain.add_field(field, eps=1.0)
    # else:
    #     h_chain.add_field(field, eps=eps)

    # h_chain.add_field(field, eps=eps)
    # h_chain.visualize()
    visualize1(h_chain, field, size_x_min, size_y_min, size_z_min, eps=3.8)

    # ---------------------------------------------------------------------------------
    # -------------------- compute Green's functions of the system --------------------
    # ---------------------------------------------------------------------------------

    num_periods = 2 * num_periods + 1

    dos = np.zeros((energy.shape[0]))
    tr = np.zeros((energy.shape[0]))
    dens = np.zeros((energy.shape[0], num_periods))

    par_data = []

    ef1 = 2.1
    ef2 = 2.1
    tempr = 100

    for j, E in enumerate(energy):
        if j % size != rank:
            continue

        L, R = tb.surface_greens_function(E, h_l, h_0, h_r, iterate=5)

        # L = L + se(E, 2.0, 2.125)
        # R = R + se(E, 2.0, 2.125)

        h_chain.add_self_energies(L, R, energy=E, tempr=tempr, ef1=ef1, ef2=ef2)
        g_trans, grd, grl, gru, gr_left, gnd, gnl, gnu, gn_left = recursive_gf(E,
                                                                               h_chain.h_l,
                                                                               h_chain.h_0,
                                                                               h_chain.h_r,
                                                                               s_in=h_chain.sgf)
        h_chain.remove_self_energies()

        for jj in range(num_periods):
            dos[j] = dos[j] + np.real(np.trace(1j * (grd[jj] - grd[jj].H))) / num_periods
            dens[j, jj] = 2 * np.trace(gnd[jj]) / num_periods

        gamma_l = 1j * (np.matrix(L) - np.matrix(L).H)
        gamma_r = 1j * (np.matrix(R) - np.matrix(R).H)
        tr[j] = np.real(np.trace(gamma_l * g_trans * gamma_r * g_trans.H))

        print("{} of {}: energy is {}".format(j + 1, energy.shape[0], E))

        if comm:
            par_data.append({'id': j, 'dos': dos[j], 'tr': tr[j], 'dens': dens[j]})

    if comm:
        par_data = comm.reduce(par_data, root=0)
        if rank == 0:
            ids = [par_data[item]['id'] for item in range(len(par_data))]
            dos = [x['dos'] for _, x in sorted(zip(ids, par_data))]
            tr = [x['tr'] for _, x in sorted(zip(ids, par_data))]
            dens = [x['dens'] for _, x in sorted(zip(ids, par_data))]
            dos = np.array(dos)
            tr = np.array(tr)
            dens = np.array(dens)

            # np.save('dos.npy', dos)

    return dos, tr, dens
def test_gf_complex_chain():
    sys.path.insert(0, '/home/mk/TB_project/tb')

    a = tb.Atom('A')
    a.add_orbital('s', -0.7)
    b = tb.Atom('B')
    b.add_orbital('s', -0.5)
    c = tb.Atom('C')
    c.add_orbital('s', -0.3)

    tb.Atom.orbital_sets = {'A': a, 'B': b, 'C': c}

    tb.set_tb_params(PARAMS_A_A={'ss_sigma': -0.5},
                     PARAMS_B_B={'ss_sigma': -0.5},
                     PARAMS_A_B={'ss_sigma': -0.5},
                     PARAMS_B_C={'ss_sigma': -0.5},
                     PARAMS_A_C={'ss_sigma': -0.5})

    xyz_file = """4
    H cell
    A1       0.0000000000    0.0000000000    0.0000000000
    B2       0.0000000000    0.0000000000    1.0000000000
    A2       0.0000000000    1.0000000000    0.0000000000
    B3       0.0000000000    1.0000000000    1.0000000000
    """

    h = tb.Hamiltonian(xyz=xyz_file, nn_distance=1.1)
    h.initialize()
    h.set_periodic_bc([[0, 0, 2.0]])
    h_l, h_0, h_r = h.get_coupling_hamiltonians()

    energy = np.linspace(-3.0, 1.5, 700)

    sgf_l = []
    sgf_r = []

    for E in energy:
        L, R = tb.surface_greens_function(E, h_l, h_0, h_r)
        sgf_l.append(L)
        sgf_r.append(R)

    sgf_l = np.array(sgf_l)
    sgf_r = np.array(sgf_r)

    num_sites = h_0.shape[0]
    gf = np.linalg.pinv(
        np.multiply.outer(energy, np.identity(num_sites)) - h_0 - sgf_l -
        sgf_r)

    tr = np.zeros((energy.shape[0]))
    dos = np.zeros((energy.shape[0]))

    for j, E in enumerate(energy):
        gf0 = np.matrix(gf[j, :, :])
        gamma_l = 1j * (np.matrix(sgf_l[j, :, :]) -
                        np.matrix(sgf_l[j, :, :]).H)
        gamma_r = 1j * (np.matrix(sgf_r[j, :, :]) -
                        np.matrix(sgf_r[j, :, :]).H)
        tr[j] = np.real(np.trace(gamma_l * gf0 * gamma_r * gf0.H))
        dos[j] = np.real(np.trace(1j * (gf0 - gf0.H)))

    np.testing.assert_allclose(dos, expected_dos_of_complex_chain(), atol=1e-5)
    np.testing.assert_allclose(tr, expected_tr_of_complex_chain(), atol=1e-5)