Beispiel #1
0
def test_double_barrier_density_recursive(single_period_test=complex_chain,
                                          periods=20):
    from negf.field import Field1D

    def qw(coord, coords_of_steps, jumps, width=1):
        ans = 0
        for j, item in enumerate(coords_of_steps):
            ans += jumps[j] * 0.5 * (np.tanh(coord - item) / width + 1.0)

        return ans

    def z_dependence(coord):
        coords_of_steps = [-15.0, -11.0, 11.0, 15.0]
        jumps = [1.7, -1.7, 1.7, -1.7]

        return qw(coord, coords_of_steps, jumps)

    f = Field1D(z_dependence, axis=2)

    ef1 = -1.3
    ef2 = -1.0
    tempr = 10

    energy, dos, tr, h, sgf_l, sgf_r = single_period_test()
    h_l, h_0, h_r = h.get_coupling_hamiltonians()
    cell = h.ct.pcv

    h_chain = HamiltonianChain(h_l, h_0, h_r, h.get_site_coordinates())
    h_chain.translate(cell[0], periods, periods)
    h_chain.add_field(f)

    num_periods = 2 * periods + 1

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

    for j, E in enumerate(energy):

        h_chain.add_self_energies(sgf_l[j, :, :],
                                  sgf_r[j, :, :],
                                  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):
            dos1[j] = dos1[j] + np.real(np.trace(
                1j * (grd[jj] - grd[jj].H))) / num_periods
            dens[j, jj] = 2 * np.trace(gnd[jj])

    np.testing.assert_allclose(np.sum(dens, axis=1)[::2],
                               expected_dens_of_complex_chain(),
                               atol=1e-1)
Beispiel #2
0
def run_for_periods_recursive(single_period_test, periods):
    energy, dos, tr, h, sgf_l, sgf_r = single_period_test()
    h_l, h_0, h_r = h.get_coupling_hamiltonians()
    cell = h.ct.pcv

    h_chain = HamiltonianChain(h_l, h_0, h_r, h.get_site_coordinates())
    h_chain.translate(cell[0], periods, periods)

    num_periods = 2 * periods + 1

    dos1 = np.zeros((energy.shape[0]))

    for j, E in enumerate(energy):

        h_chain.add_self_energies(sgf_l[j, :, :], sgf_r[j, :, :])
        grd, grl, gru, gr_left = recursive_gf(E, h_chain.h_l, h_chain.h_0,
                                              h_chain.h_r)
        h_chain.remove_self_energies()

        for jj in range(len(grd)):
            dos1[j] = dos1[j] + np.real(np.trace(
                1j * (grd[jj] - grd[jj].H))) / num_periods

    np.testing.assert_allclose(dos, dos1, atol=1e-2)
Beispiel #3
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
Beispiel #4
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
Beispiel #5
0
                                               save=False)

mat_l_list, mat_d_list, mat_u_list = h.h_l, h.h_0, h.h_r

# energy = energy[5:25]

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

for j, E in enumerate(energy):
    print(j)

    mat_d_list[0] = mat_d_list[0] + sgf_r[j, :, :]
    mat_d_list[-1] = mat_d_list[-1] + sgf_l[j, :, :]

    g_trans, grd, grl, gru, gr_left = recursive_gf(E, mat_l_list, mat_d_list,
                                                   mat_u_list)

    mat_d_list[0] = mat_d_list[0] - sgf_r[j, :, :]
    mat_d_list[-1] = mat_d_list[-1] - sgf_l[j, :, :]

    for jj in range(len(grd)):
        dos[j] = dos[j] + np.real(np.trace(1j * (grd[jj] - grd[jj].H)))

    gamma_l = 1j * (np.matrix(sgf_r[j, :, :]) - np.matrix(sgf_r[j, :, :]).H)
    gamma_r = 1j * (np.matrix(sgf_l[j, :, :]) - np.matrix(sgf_l[j, :, :]).H)
    tr[j] = np.real(np.trace(gamma_l * g_trans * gamma_r * g_trans.H))

ax = plt.axes()
ax.set_xlabel('Energy (eV)')
ax.set_ylabel('DOS')
ax.plot(energy, dos)