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