def parametric_hopping_hamiltonian(h, cutoff=5, fc=None, rcut=5.0): """ Gets a first neighbor hamiltonian""" from neighbor import parametric_hopping if fc is None: rcut = 2.1 # stop in this neighbor def fc(r1, r2): r = r1 - r2 r = r.dot(r) if 0.9 < r < 1.1: return 1.0 else: return 0.0 r = h.geometry.r # x coordinate g = h.geometry h.is_multicell = True # first neighbors hopping, all the matrices a1, a2, a3 = g.a1, g.a2, g.a3 h.intra = h.spinless2full(parametric_hopping(r, r, fc)) # intra matrix # generate directions dirs = h.geometry.neighbor_directions() # directions of the hoppings # generate hoppings h.hopping = [] # empty list for d in dirs: # loop over directions i1, i2, i3 = d[0], d[1], d[2] # extract indexes if i1 == 0 and i2 == 0 and i3 == 0: continue t = Hopping() # hopping class da = a1 * i1 + a2 * i2 + a3 * i3 # direction r2 = [ri + da for ri in r] if not close_enough(r, r2, rcut=rcut): # check if we can skip this one # print("Skipping hopping",[i1,i2,i3]) continue t.m = h.spinless2full(parametric_hopping(r, r2, fc)) t.dir = [i1, i2, i3] # store direction h.hopping.append(t) # append return h
def set_couplings(g,f=None): """Set the exchange couplings""" js = [] xs = [] ys = [] if callable(f): # callable function m = neighbor.parametric_hopping(g.r,g.r) else: raise return m # return pairs
def generate_parametric_hopping(h,f): """ Adds a parametric hopping to the hamiltonian based on an input function""" rs = h.geometry.r # positions g = h.geometry # geometry h.has_spin = False if h.is_sparse: data = [] rows = [] cols = [] if h.dimensionality == 0: for i in range(len(rs)): for j in range(len(rs)): c = f(rs[i],rs[j]) # get coupling if np.abs(c)>0.001: #cutoff rows.append(i) cols.append(j) data.append(c) n = len(rs) # dimension of the matrix h.intra = csc_matrix((data,(rows,cols)),shape=(n,n)) # store in hamil else: raise # error if not 0d return h else: # not sparse h.intra = parametric_hopping(rs,rs,f) if h.dimensionality == 0: pass elif h.dimensionality == 1: dr = np.array([g.celldis,0.,0.]) h.inter = parametric_hopping(rs,rs+dr,f) elif h.dimensionality == 2: h.tx = parametric_hopping(rs,rs+g.a1,f) h.ty = parametric_hopping(rs,rs+g.a2,f) h.txy = parametric_hopping(rs,rs+g.a1+g.a2,f) h.txmy = parametric_hopping(rs,rs+g.a1-g.a2,f) else: raise return h
def biterminal(self, right_g=None, left_g=None, central_g=None, fun=None, disorder=0.0): """Create the matrices for a biterminal device, based on geometries""" if fun is None: # no function provided def fun(r1, r2): dr = r1 - r2 if .7 < dr.dot(dr) < 1.3: return True else: return False leadr = Lead() # right lead leadl = Lead() # left lead Rr = right_g.r # positions Lr = left_g.r # positions Cr = central_g.r # positions leadr.intra = neighbor.parametric_hopping(Rr, Rr, fun) # intra term leadl.intra = neighbor.parametric_hopping(Lr, Lr, fun) # intra term intra = neighbor.parametric_hopping(Cr, Cr, fun) # intra term for i in range(intra.shape[0]): # add disorder intra[i, i] += disorder * (np.random.random() - .5) self.intra = intra # store leadr.coupling = neighbor.parametric_hopping(Rr, Cr, fun) # coupling leadl.coupling = neighbor.parametric_hopping(Lr, Cr, fun) # coupling # now coupling within the lead Rr_dis = [r - right_g.a1 for r in Rr] # displace Lr_dis = [r - left_g.a1 for r in Lr] # displace leadr.inter = neighbor.parametric_hopping(Rr, Rr_dis, fun) # intra term leadl.inter = neighbor.parametric_hopping(Lr, Lr_dis, fun) # intra term # store positions leadr.r = Rr leadl.r = Lr self.r = Cr # store leads self.leads = [leadr, leadl] # store the leads