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)
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)
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
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
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)