def comm_angular(x,y,z): from scipy.sparse import csc_matrix as csc xy = x*y - y*x xy = xy - 1j*z if np.abs(np.max(xy))>0.001: print csc(xy) raise
def intra_super2d(h,n=1,central=None): """ Calculates the intra of a 2d system""" from scipy.sparse import bmat from scipy.sparse import csc_matrix as csc tx = csc(h.tx) ty = csc(h.ty) txy = csc(h.txy) txmy = csc(h.txmy) intra = csc(h.intra) for i in range(n): intrasuper[i][i] = intra # intracell (x1,y1) = inds[i] for j in range(n): (x2,y2) = inds[j] dx = x2-x1 dy = y2-y1 if dx==1 and dy==0: intrasuper[i][j] = tx if dx==-1 and dy==0: intrasuper[i][j] = tx.H if dx==0 and dy==1: intrasuper[i][j] = ty if dx==0 and dy==-1: intrasuper[i][j] = ty.H if dx==1 and dy==1: intrasuper[i][j] = txy if dx==-1 and dy==-1: intrasuper[i][j] = txy.H if dx==1 and dy==-1: intrasuper[i][j] = txmy if dx==-1 and dy==1: intrasuper[i][j] = txmy.H # substitute the central cell if it is the case if central!=None: ic = (n-1)/2 intrasuper[ic][ic] = central # now convert to matrix intrasuper = bmat(intrasuper).todense() # supercell return intrasuper
def supercell(h,nsuper,sparse=False): """ Get a supercell of the system, h is the hamiltonian nsuper is the number of replicas """ from scipy.sparse import csc_matrix as csc from scipy.sparse import bmat from copy import deepcopy hout = deepcopy(h) # output hamiltonian intra = csc(h.intra) # intracell matrix inter = csc(h.inter) # intercell matrix # crease supercells block matrices intra_super = [[None for i in range(nsuper)] for j in range(nsuper)] inter_super = [[None for i in range(nsuper)] for j in range(nsuper)] for i in range(nsuper): # onsite part intra_super[i][i] = intra inter_super[i][i] = 0.0*intra for i in range(nsuper-1): # inter minicell part intra_super[i][i+1] = inter intra_super[i+1][i] = inter.H inter_super[nsuper-1][0] = inter # inter supercell part inter_super[0][nsuper-1] = inter.H # inter supercell part # create dense matrices if not sparse: intra_super = bmat(intra_super).todense() inter_super = bmat(inter_super).todense() # add to the output hamiltonian hout.intra = intra_super hout.inter = inter_super import geometry hout.geometry = h.geometry.supercell(nsuper) return hout
def hubbard(h,U=1.0,pairs = []): """ Creates mean field matrices for the input hamiltonian, returns list with mena field amtrix pairs in csc form""" hubm = [] # list with the hubbard mean field matrices if len(pairs)==0: de = len(h.intra) # dimension of the hamiltonian if h.has_eh: de = de/2 # only dimension of electrons (not holes!) pairs = range(de/2) # create list with oribtal indices for i in pairs: # loop over up down pairs # density density term data = [1.0+0.j] # value of the term in the matrix ij = [[2*i],[2*i]] # indexes in the matrix a = csc((data,ij),shape=(de,de)) ij = [[2*i+1],[2*i+1]] # indexes in the matrix b = csc((data,ij),shape=(de,de)) hubm += [pair_mf(a,b,g=U)] # add mean field pair # exchange exchange term data = [1.0+0.j] # value of the term in the matrix ij = [[2*i],[2*i+1]] # indexes in the matrix a = csc((data,ij),shape=(de,de)) ij = [[2*i+1],[2*i]] # indexes in the matrix b = csc((data,ij),shape=(de,de)) hubm += [pair_mf(a,b,g= -U)] # add mean field pair return hubm # return list with the pairs
def supercell_selfenergy(h, e=0.0, delta=0.001, nk=100, nsuper=[1, 1]): """alculates the selfenergy of a certain supercell """ try: # if two number given nsuper1 = nsuper[0] nsuper2 = nsuper[1] except: # if only one number given nsuper1 = nsuper nsuper2 = nsuper print "Supercell", nsuper1, "x", nsuper2 ez = e + 1j * delta # create complex energy import dyson2d g = dyson2d.dyson2d(h.intra, h.tx, h.ty, h.txy, h.txmy, nsuper1, nsuper2, 300, ez) g = np.matrix(g) # convert to matrix n = nsuper1 * nsuper2 # number of cells intrasuper = [[None for j in range(n)] for i in range(n)] # create indexes (same order as in fortran routine) k = 0 inds = [] for i in range(nsuper1): for j in range(nsuper2): inds += [(i, j)] k += 1 # create hamiltonian of the supercell from scipy.sparse import bmat from scipy.sparse import csc_matrix as csc tx = csc(h.tx) ty = csc(h.ty) txy = csc(h.txy) txmy = csc(h.txmy) intra = csc(h.intra) for i in range(n): intrasuper[i][i] = intra # intracell (x1, y1) = inds[i] for j in range(n): (x2, y2) = inds[j] dx = x2 - x1 dy = y2 - y1 if dx == 1 and dy == 0: intrasuper[i][j] = tx if dx == -1 and dy == 0: intrasuper[i][j] = tx.H if dx == 0 and dy == 1: intrasuper[i][j] = ty if dx == 0 and dy == -1: intrasuper[i][j] = ty.H if dx == 1 and dy == 1: intrasuper[i][j] = txy if dx == -1 and dy == -1: intrasuper[i][j] = txy.H if dx == 1 and dy == -1: intrasuper[i][j] = txmy if dx == -1 and dy == 1: intrasuper[i][j] = txmy.H intrasuper = bmat(intrasuper).todense() # supercell eop = np.matrix(np.identity(len(g), dtype=np.complex)) * (ez) selfe = eop - intrasuper - g.I return g, selfe
def local_dos(m_in,i=0,n=200): """ Calculates local DOS using the KPM""" m = csc(m_in) # saprse matrix nd = m.shape[0] # length of the matrix mus = np.array([0.0j for j in range(2*n)]) v = rand.random(nd)*0. v[i] = 1.0 # vector only in site i v = csc(v).transpose() mus += get_moments(v,m,n=n) # get the chebychev moments return mus
def full_trace_A(m_in,ntries=20,n=200,A=None): """ Calculates local DOS using the KPM""" m = csc(m_in) # saprse matrix nd = m.shape[0] # length of the matrix mus = np.array([0.0j for j in range(2*n)]) for i in range(nd): # loop over tries #v = rand.random(nd) - .5 v = rand.random(nd)*0. v[i] = 1.0 # vector only in site i v = csc(v).transpose() mus += get_momentsA(v,m,n=n,A=A) # get the chebychev moments return mus/nd
def random_trace(m_in,ntries=20,n=200): """ Calculates local DOS using the KPM""" m = csc(m_in) # saprse matrix nd = m.shape[0] # length of the matrix mus = np.array([0.0j for j in range(2*n)]) for i in range(ntries): # loop over tries #v = rand.random(nd) - .5 v = rand.random(nd) -.5 + 1j*rand.random(nd) -.5j v = v/np.sqrt(v.dot(v)) # normalize the vector v = csc(v).transpose() mus += get_moments(v,m,n=n) # get the chebychev moments return mus/ntries
def full_trace(m_in,n=200,ntries=100): """ Get full trace of the matrix""" m = csc(m_in) # saprse matrix nd = m.shape[0] # length of the matrix mus = np.array([0.0j for i in range(2*n)]) # for i in range(ntries): for i in range(nd/2-1,nd/2): v = rand.random(nd)*0. v[i] = 1.0 # v = v/np.sqrt(v.dot(v)) # normalize the vector v = csc(v).transpose() mus += get_moments(v,m,n=n) return mus/ntries
def get_representation(wfs,A): """ Gets the matrix representation of a certain operator """ n = len(wfs) # number of eigenfunctions ma = np.zeros((n,n),dtype=np.complex) # representation of A sa = csc(A) # sparse matrix for i in range(n): vi = csc(np.conjugate(wfs[i])) # first wavefunction for j in range(n): vj = csc(wfs[j]).transpose() # second wavefunction data = (vi*sa*vj).todense()[0,0] ma[i,j] = data return ma
def interface_multienergy(h1,h2,k=[0.0,0.,0.],energies=[0.0],delta=0.01, dh1=None,dh2=None): """Get the Green function of an interface""" from scipy.sparse import csc_matrix as csc from scipy.sparse import bmat fun1 = green_kchain_evaluator(h1,k=k,delta=delta,hs=None, only_bulk=False,reverse=True) # surface green function fun2 = green_kchain_evaluator(h2,k=k,delta=delta,hs=None, only_bulk=False,reverse=False) # surface green function out = [] # output for energy in energies: # loop gs1,sf1 = fun1(energy) gs2,sf2 = fun2(energy) ############# ## 1 C 2 ## ############# # Now apply the Dyson equation (ons1,hop1) = get1dhamiltonian(h1,k,reverse=True) # get 1D Hamiltonian (ons2,hop2) = get1dhamiltonian(h2,k,reverse=False) # get 1D Hamiltonian havg = (hop1.H + hop2)/2. # average hopping if dh1 is not None: ons1 = ons1 + dh1 if dh2 is not None: ons2 = ons2 + dh2 ons = bmat([[csc(ons1),csc(havg)],[csc(havg.H),csc(ons2)]]) # onsite self2 = bmat([[csc(ons1)*0.0,None],[None,csc(hop2@[email protected])]]) self1 = bmat([[csc(hop1@[email protected]),None],[None,csc(ons2)*0.0]]) # Dyson equation ez = (energy+1j*delta)*np.identity(ons1.shape[0]+ons2.shape[0]) # energy ginter = (ez - ons - self1 - self2).I # Green function # now return everything, first, second and hybrid out.append([gs1,sf1,gs2,sf2,ginter]) return out # return output
def random_trace(m_in,ntries=20,n=200,fun=None,operator=None): """ Calculates local DOS using the KPM""" if fun is not None: # check that dimensions are fine v0 = fun() if len(v0) != m_in.shape[0]: raise if fun is None: # def fun(): return rand.random(nd) -.5 + 1j*rand.random(nd) -.5j def fun(): return (rand.random(nd) - 0.5)*np.exp(2*1j*np.pi*rand.random(nd)) m = csc(m_in) # saprse matrix nd = m.shape[0] # length of the matrix def pfun(x): v = fun() v = v/np.sqrt(v.dot(np.conjugate(v))) # normalize the vector # v = csc(v).transpose() if operator is None: mus = get_moments(v,m,n=n) # get the chebychev moments else: mus = get_momentsA(v,m,n=2*n,A=operator) # get the chebychev moments return mus # from . import parallel out = [pfun(i) for i in range(ntries)] # perform all the computations # out = parallel.pcall(pfun,range(ntries)) mus = np.zeros(out[0].shape,dtype=np.complex) for o in out: mus = mus + o # add contribution return mus/ntries
def loadAnyMat(fn, data_elem=None): ''' Load up arbitrary.mat matrix as a csc matrix @param fn: the filename @param data_ele: the data element item name ''' from scipy.io import loadmat from scipy.sparse import csc_matrix as csc G = loadmat(fn) if data_elem: try: G = G[data_elem] except: return "[IOERROR]: The data element '%s' you provided was not found." % data_elem else: key = set(G.keys()) - set(['__version__', '__header__', '__globals__']) key = list(key) if len(key) > 1: return "[ERROR]: Too many data elements to distinguish the graph - use only one data element or specify explicitly" else: G = G[key[0]] if not isinstance(G, csc): G = csc(G) return G
def random_trace(m_in,ntries=20,n=200,fun=None): """ Calculates local DOS using the KPM""" if fun is not None: # check that dimensions are fine v0 = fun() if len(v0) != m_in.shape[0]: raise if fun is None: def fun(): return rand.random(nd) -.5 + 1j*rand.random(nd) -.5j m = csc(m_in) # saprse matrix nd = m.shape[0] # length of the matrix mus = np.array([0.0j for j in range(2*n)]) for i in range(ntries): # loop over tries v = fun() v = v/np.sqrt(v.dot(np.conjugate(v))) # normalize the vector v = csc(v).transpose() mus += get_moments(v,m,n=n) # get the chebychev moments return mus/ntries
def surface(h,cut = 2.,which="both"): """Return an operator which is non-zero in the upper surface""" zmax = np.max(h.geometry.z) # maximum z zmin = np.min(h.geometry.z) # maximum z dind = 1 # index to which divide the positions if h.has_spin: dind *= 2 # duplicate for spin if h.has_eh: dind *= 2 # duplicate for eh n = h.intra.shape[0] # number of elments of the hamiltonian data = [] # epmty list for i in range(n): # loop over elements z = h.geometry.z[i//dind] if which=="upper": # only the upper surface if np.abs(z-zmax) < cut: data.append(1.) else: data.append(0.) elif which=="lower": # only the upper surface if np.abs(z-zmin) < cut: data.append(1.) else: data.append(0.) elif which=="both": # only the upper surface if np.abs(z-zmax) < cut: data.append(1.) elif np.abs(z-zmin) < cut: data.append(-1.) else: data.append(0.) else: raise row, col = range(n),range(n) m = csc((data,(row,col)),shape=(n,n),dtype=np.complex) return m # return the operator
def generate_soc(specie,value,input_file="wannier.win",nsuper=1): """Add SOC to a hamiltonian based on wannier.win""" o = open(".soc.status","w") iat = 1 # atom counter orbnames = names_soc_orbitals(specie) # get which are the orbitals ls = soc_l((len(orbnames)-1)/2) # get the SOC matrix norb = get_num_wannier(input_file) # number of wannier orbitals m = np.matrix([[0.0j for i in range(norb*2)] for j in range(norb*2)]) # matrix nat = get_num_atoms(specie,input_file) # number of atoms of this specie for iat in range(nat): # try: # fo.write("Attempting "+specie+" "+str(iat+1)+"\n") for i in range(len(orbnames)): # loop over one index orbi = orbnames[i] for j in range(len(orbnames)): # loop over other index orbj = orbnames[j] ii = get_index_orbital(specie,iat+1,orbi) # index in wannier jj = get_index_orbital(specie,iat+1,orbj) # index in wannier # fo.write(str(ii)+" "+str(jj)+"\n") ii += -1 # python starts in 0 jj += -1 # python starts in 0 m[2*ii,2*jj] = ls[2*i,2*j] # store the soc coupling m[2*ii+1,2*jj] = ls[2*i+1,2*j] # store the soc coupling m[2*ii,2*jj+1] = ls[2*i,2*j+1] # store the soc coupling m[2*ii+1,2*jj+1] = ls[2*i+1,2*j+1] # store the soc coupling # return # except: break # fo.close() n = nsuper**2 # supercell mo = [[None for i in range(n)] for j in range(n)] for i in range(n): mo[i][i] = csc(m) # diagonal elements mo = bmat(mo).todense() # dense matrix return mo*value # return matrix
def directional_abg(v = np.array([0.,0.,1.]),i=0,d=1,g=1.0): """Calculates a pair of mean field matrices for a particular site""" r = np.sqrt(v[0]**2 + v[1]**2) # radial vector in xy theta = np.arctan2(r,v[2]) # calculate theta phi = np.arctan2(v[1],v[0]) # calculate phi t,p = theta, phi # store in easiest variables ct,st = np.cos(t/2.0), np.sin(t/2.0) # sin and cosine e, ce = np.exp(1j*p), np.exp(-1j*p) # complex phase ij=[[2*i,2*i],[2*i,2*i+1],[2*i+1,2*i],[2*i+1,2*i+1]] # index row=[2*i,2*i,2*i+1,2*i+1] # index col=[2*i,2*i+1,2*i,2*i+1] # index data1=[ct*ct,ct*st*ce,ct*st*e,st*st] # values of the matrix A data2=[st*st,-ct*st*ce,-ct*st*e,ct*ct] # values of B a = csc((data1,(row,col)),shape=(d,d)) # create A b = csc((data2,(row,col)),shape=(d,d)) # create B abg = pair_mf(a,b,g=g) # create the A, B, coupling object return abg
def add_interlayer(t,ri,rj,has_spin=True,is_sparse=True): """Calculate interlayer coupling""" m = np.matrix([[0. for i in ri] for j in rj]) if has_spin: m = bmat([[csc(m),None],[None,csc(m)]]).todense() zi = [r[2] for r in ri] zj = [r[2] for r in rj] for i in range(len(ri)): # add the interlayer for j in range(len(ri)): # add the interlayer rij = ri[i] - rj[j] # distance between atoms dz = zi[i] - zj[j] # vertical distance if (3.99<rij.dot(rij)<4.01) and (3.99<(dz*dz)<4.01): # check if connect if has_spin: # spin polarized m[2*i,2*j] = t m[2*i+1,2*j+1] = t else: # spin unpolarized m[i,j] = t return m
def full_trace(m_in,n=200,use_fortran=True): """ Get full trace of the matrix""" m = csc(m_in) # saprse matrix nd = m.shape[0] # length of the matrix mus = np.array([0.0j for i in range(2*n)]) # for i in range(ntries): for i in range(nd): mus += local_dos(m_in,i=i,n=n,use_fortran=use_fortran) return mus/nd
def get_sz(h): """Operator for the calculation of Sz expectation value""" if h.has_eh: raise if not h.has_spin: raise if h.has_spin: op = np.zeros(h.intra.shape,dtype=np.complex) # initialize matrix for i in range(len(op)): op[i,i] = (-1.)**i if h.is_sparse: op = csc(op) # transform into sparse return op
def supercell(h,nsuper,sparse=False): """ Get a supercell of the system, h is the hamiltonian nsuper is the number of replicas """ from scipy.sparse import csc_matrix as csc from scipy.sparse import bmat from copy import deepcopy hout = deepcopy(h) # output hamiltonian intra = csc(h.intra) # intracell matrix inter = csc(h.inter) # intercell matrix # crease supercells block matrices intra_super = [[None for i in range(nsuper)] for j in range(nsuper)] inter_super = [[None for i in range(nsuper)] for j in range(nsuper)] for i in range(nsuper): # onsite part intra_super[i][i] = intra inter_super[i][i] = 0.0*intra for i in range(nsuper-1): # inter minicell part intra_super[i][i+1] = inter intra_super[i+1][i] = inter.H inter_super[nsuper-1][0] = inter # inter supercell part # create dense matrices if not sparse: intra_super = bmat(intra_super).todense() inter_super = bmat(inter_super).todense() # add to the output hamiltonian hout.intra = intra_super hout.inter = inter_super # get the old geometry geometry y = hout.geometry.y x = hout.geometry.x celldis = hout.geometry.celldis # position of the supercell yout = [] xout = [] for i in range(nsuper): yout += y.tolist() xout += (x+i*celldis).tolist() # now modify the geometry hout.geometry.x = np.array(xout) hout.geometry.y = np.array(yout) hout.geometry.celldis = celldis*nsuper return hout
def eigenvectors(h,nk=10): import scipy.linalg as lg from scipy.sparse import csc_matrix as csc if h.dimensionality==0: vv = lg.eigh(h.intra) vecs = [csc(np.matrix(v).T) for v in vv[1].transpose()] return vv[0],vecs elif h.dimensionality==1: kp = np.linspace(0.,1.0,nk) eigvecs = [] # empty list with eigenvectors eigvals = [] # empty list with eigenvectors f = h.get_hk_gen() for k in kp: # loop over kpoints hk = f(k) # kdependent hamiltonian vv = lg.eigh(hk) # diagonalize k hamiltonian eigvals += vv[0].tolist() # store eigenvalues vecs = [csc(np.matrix(v).T) for v in vv[1].transpose()] eigvecs += vecs # store eigenvectors in sparse form return eigvals,eigvecs else: raise
def honeycomb2squareMoS2(h,check=True): """Transforms a honeycomb lattice into a square lattice""" ho = deepcopy(h) # output geometry g = h.geometry # geometry go = deepcopy(g) # output geometry go.a1 = g.a1 + g.a2 go.a2 = g.a1 - g.a2 # now put the first vector along the x axis go.r = np.concatenate([g.r,g.r + g.a1]) go.r2xyz() go = sculpt.rotate_a2b(go,go.a1,np.array([1.,0.,0.])) # perform a check to see if the supercell is well built a1a2 = go.a1.dot(go.a2) # if a1a2>0.001: if np.abs(go.a1)[1]>0.001 or np.abs(go.a2[0])>0.001: ang = go.a1.dot(go.a2) print("The projection of lattice vectors is",ang) if check: raise go.r2xyz() # update r atribbute zero = csc(h.tx*0.) # define sparse intra = csc(h.intra) tx = csc(h.tx) ty = csc(h.ty) txy = csc(h.txy) txmy = csc(h.txmy) # define new hoppings ho.intra = bmat([[intra,tx],[tx.H,intra]]).todense() ho.tx = bmat([[txy,zero],[ty,txy]]).todense() ho.ty = bmat([[txmy,zero],[ty.H,txmy]]).todense() ho.txy = bmat([[zero,zero],[tx,zero]]).todense() ho.txmy = bmat([[zero,zero],[zero,zero]]).todense() ho.geometry = go return ho
def honeycomb2square(h): """Transforms a honeycomb lattice into a square lattice""" ho = deepcopy(h) # output geometry g = h.geometry # geometry go = deepcopy(g) # output geometry go.a1 = - g.a1 - g.a2 go.a2 = g.a1 - g.a2 go.x = np.concatenate([g.x,g.x-g.a1[0]]) go.y = np.concatenate([g.y,g.y-g.a1[1]]) go.z = np.concatenate([g.z,g.z]) go.xyz2r() # update r atribbute zero = csc(h.tx*0.) # define sparse intra = csc(h.intra) tx = csc(h.tx) ty = csc(h.ty) txy = csc(h.txy) txmy = csc(h.txmy) # define new hoppings ho.intra = bmat([[intra,tx.H],[tx,intra]]).todense() ho.tx = bmat([[txy.H,zero],[ty.H,txy.H]]).todense() ho.ty = bmat([[txmy,ty.H],[txmy,zero]]).todense() ho.txy = bmat([[zero,None],[None,zero]]).todense() ho.txmy = bmat([[zero,zero],[tx.H,zero]]).todense() ho.geometry = go return ho
def bulk2ribbon(h,n=10): """Converts a hexagonal bulk hamiltonian into a ribbon hamiltonian""" go = h.geometry.copy() # copy geometry ho = h.copy() # copy hamiltonian ho.dimensionality = 1 # reduce dimensionality ho.geometry.dimensionality = 1 # reduce dimensionality intra = [[None for i in range(n)] for j in range(n)] inter = [[None for i in range(n)] for j in range(n)] for i in range(n): # to the the sam index intra[i][i] = csc(h.intra) inter[i][i] = csc(h.tx) for i in range(n-1): # one more or less intra[i][i+1] = csc(h.ty) intra[i+1][i] = csc(h.ty.H) inter[i+1][i] = csc(h.txmy) inter[i][i+1] = csc(h.txy) ho.intra = bmat(intra).todense() ho.inter = bmat(inter).todense() # calculate the angle import sculpt go = sculpt.rotate_a2b(go,go.a1,np.array([1.,0.,0.])) ho.geometry.celldis = go.a1[0] # first eigenvector r = [] for i in range(n): for ri in go.r: r.append(ri+i*go.a2) ho.geometry.r = np.array(r) ho.geometry.r2xyz() # get r positions return ho
def supercell_selfenergy(h,e=0.0,delta=0.001,nk=100,nsuper=1): """alculates the selfenergy of a certain supercell """ ez = e + 1j*delta # create complex energy import dyson2d g = dyson2d.dyson2d(h.intra,h.tx,h.ty,h.txy,h.txmy,nsuper,nsuper,300,ez) g = np.matrix(g) # convert to matrix n = nsuper*nsuper # number of cells intrasuper = [[None for j in range(n)] for i in range(n)] # create indexes (same order as in fortran routine) k = 0 inds = [] for i in range(nsuper): for j in range(nsuper): inds += [(j,i)] k += 1 # create hamiltonian of the supercell from scipy.sparse import bmat from scipy.sparse import csc_matrix as csc tx = csc(h.tx) ty = csc(h.ty) txy = csc(h.txy) txmy = csc(h.txmy) intra = csc(h.intra) for i in range(n): intrasuper[i][i] = intra # intracell (x1,y1) = inds[i] for j in range(n): (x2,y2) = inds[j] if (x1-x2)==1 and (y1-y2)==0: intrasuper[i][j] = tx if (x1-x2)==-1 and (y1-y2)==0: intrasuper[i][j] = tx.H if (x1-x2)==0 and (y1-y2)==1: intrasuper[i][j] = ty if (x1-x2)==0 and (y1-y2)==-1: intrasuper[i][j] = ty.H if (x1-x2)==1 and (y1-y2)==1: intrasuper[i][j] = txy if (x1-x2)==-1 and (y1-y2)==-1: intrasuper[i][j] = txy.H if (x1-x2)==1 and (y1-y2)==-1: intrasuper[i][j] = txmy if (x1-x2)==-1 and (y1-y2)==1: intrasuper[i][j] = txmy.H intrasuper = bmat(intrasuper).todense() # supercell eop = np.matrix(np.identity(len(g),dtype=np.complex))*(ez) selfe = eop - intrasuper - g.I return g,selfe,intrasuper
def get_rop(h,fun): """Operator for the calculation of a position expectation value""" rep = 1 # repetitions if h.has_spin: rep *= 2 if h.has_eh: rep *= 2 data = [] for ri in h.geometry.r: for i in range(rep): data.append(fun(ri)) # store n = h.intra.shape[0] row = range(n) col = range(n) m = csc((data,(row,col)),shape=(n,n),dtype=np.complex) return m
def interface1d(h,cut = 3.): dind = 1 # index to which divide the positions if h.has_spin: dind *= 2 # duplicate for spin if h.has_eh: dind *= 2 # duplicate for eh n = h.intra.shape[0] # number of elments of the hamiltonian data = [] # epmty list for i in range(n): # loop over elements y = h.geometry.y[i//dind] if np.abs(y)<cut: data.append(1.) # if it belongs to the interface else: data.append(0.) # otherwise row, col = range(n),range(n) m = csc((data,(row,col)),shape=(n,n),dtype=np.complex) return m # return the operator
def ldos_finite(h,e=0.0,n=10,nwf=4,delta=0.0001): """Calculate the density of states for a finite system""" if h.dimensionality!=1: raise # if it is not one dimensional intra = csc(h.intra) # convert to sparse inter = csc(h.inter) # convert to sparse interH = inter.H # hermitian m = [[None for i in range(n)] for j in range(n)] # full matrix for i in range(n): # add intracell m[i][i] = intra for i in range(n-1): # add intercell m[i][i+1] = inter m[i+1][i] = interH m = bmat(m) # convert to matrix (ene,wfs) = slg.eigsh(m,k=nwf,which="LM",sigma=0.0) # diagonalize wfs = wfs.transpose() # transpose wavefunctions dos = (wfs[0].real)*0.0 # calculate dos for (ie,f) in zip(ene,wfs): # loop over waves c = 1./(1.+((ie-e)/delta)**2) # calculate coefficient dos += np.abs(f)*c # add contribution odos = spatial_dos(h,dos) # get the spatial distribution go = h.geometry.supercell(n) # get the supercell write_ldos(go.x,go.y,odos) # write in a file return dos # return the dos
def interface1d(h,cut = 3.): dind = 1 # index to which divide the positions if h.has_spin: dind *= 2 # duplicate for spin if h.has_eh: dind *= 2 # duplicate for eh n = len(h.intra) # number of elments of the hamiltonian data = [] # epmty list for i in range(n): # loop over elements y = h.geometry.y[i/dind] if y < -cut: data.append(-1.) elif y > cut: data.append(1.) else: data.append(0.) row, col = range(n),range(n) m = csc((data,(row,col)),shape=(n,n),dtype=np.complex) return m # return the operator
def get_interface(h, fun=None): """Return an operator that projects onte the interface""" dind = 1 # index to which divide the positions if h.has_spin: dind *= 2 # duplicate for spin if h.has_eh: dind *= 2 # duplicate for eh iden = csc(np.matrix(np.identity(dind, dtype=np.complex))) # identity matrix r = h.geometry.r # positions out = [[None for ri in r] for rj in r] # initialize if fun is None: # no input function cut = 2.0 # cutoff if h.dimensionality == 1: index = 1 elif h.dimensionality == 2: index = 2 else: raise def fun(ri): # define the function if np.abs(ri[index]) < cut: return 1.0 else: return 0.0 for i in range(len(r)): # loop over positions out[i][i] = fun(r[i]) * iden return bmat(out) # return matrix
def generate_soc(specie,value,input_file="wannier.win",nsuper=1,path=None): """Add SOC to a hamiltonian based on wannier.win""" if path is not None: inipath = os.getcwd() # current path os.chdir(path) # go there o = open(".soc.status","w") iat = 1 # atom counter orbnames = names_soc_orbitals(specie) # get which are the orbitals ls = soc_l((len(orbnames)-1)/2) # get the SOC matrix norb = get_num_wannier(input_file) # number of wannier orbitals m = np.matrix([[0.0j for i in range(norb*2)] for j in range(norb*2)]) # matrix nat = get_num_atoms(specie,input_file) # number of atoms of this specie for iat in range(nat): # try: # fo.write("Attempting "+specie+" "+str(iat+1)+"\n") for i in range(len(orbnames)): # loop over one index orbi = orbnames[i] for j in range(len(orbnames)): # loop over other index orbj = orbnames[j] ii = get_index_orbital(specie,iat+1,orbi) # index in wannier jj = get_index_orbital(specie,iat+1,orbj) # index in wannier # fo.write(str(ii)+" "+str(jj)+"\n") ii += -1 # python starts in 0 jj += -1 # python starts in 0 m[2*ii,2*jj] = ls[2*i,2*j] # store the soc coupling m[2*ii+1,2*jj] = ls[2*i+1,2*j] # store the soc coupling m[2*ii,2*jj+1] = ls[2*i,2*j+1] # store the soc coupling m[2*ii+1,2*jj+1] = ls[2*i+1,2*j+1] # store the soc coupling # return # except: break # fo.close() n = nsuper**2 # supercell mo = [[None for i in range(n)] for j in range(n)] for i in range(n): mo[i][i] = csc(m) # diagonal elements mo = bmat(mo).todense() # dense matrix if path is not None: os.chdir(inipath) # go there print(np.max(np.abs(mo))) return np.matrix(mo*value) # return matrix
def get_surface(h, cut=0.5, which="both"): """Return an operator which is non-zero in the upper surface""" zmax = np.max(h.geometry.r[:, 2]) # maximum z zmin = np.min(h.geometry.r[:, 2]) # maximum z dind = 1 # index to which divide the positions n = len(h.geometry.r) # number of elments of the hamiltonian data = [] # epmty list for i in range(n): # loop over elements z = h.geometry.z[i] if which == "upper": # only the upper surface if np.abs(z - zmax) < cut: data.append(1.) else: data.append(0.) elif which == "lower": # only the upper surface if np.abs(z - zmin) < cut: data.append(1.) else: data.append(0.) elif which == "both": # only the upper surface if np.abs(z - zmax) < cut: data.append(1.) elif np.abs(z - zmin) < cut: data.append(1.) else: data.append(0.) else: raise row, col = range(n), range(n) m = csc((data, (row, col)), shape=(n, n), dtype=np.complex) m = h.spinless2full(m) return m # return the operator
def random_trace(m_in,ntries=20,n=200,fun=None,operator=None): """ Calculates local DOS using the KPM""" if fun is not None: # check that dimensions are fine v0 = fun() if len(v0) != m_in.shape[0]: raise if fun is None: # def fun(): return rand.random(nd) -.5 + 1j*rand.random(nd) -.5j def fun(): return (rand.random(nd) - 0.5)*np.exp(2*1j*np.pi*rand.random(nd)) m = csc(m_in) # saprse matrix nd = m.shape[0] # length of the matrix def pfun(x): v = fun() v = v/np.sqrt(v.dot(np.conjugate(v))) # normalize the vector # v = csc(v).transpose() if operator is None: mus = get_moments(v,m,n=n) # get the chebychev moments else: mus = get_momentsA(v,m,n=2*n,A=operator) # get the chebychev moments return mus from . import parallel out = parallel.pcall(pfun,range(ntries)) mus = np.zeros(out[0].shape,dtype=np.complex) for o in out: mus = mus + o # add contribution return mus/ntries
def bulk2ribbon(h, n=10): """Converts a hexagonal bulk hamiltonian into a ribbon hamiltonian""" go = h.geometry.copy() # copy geometry ho = h.copy() # copy hamiltonian ho.dimensionality = 1 # reduce dimensionality go.dimensionality = 1 # reduce dimensionality intra = [[None for i in range(n)] for j in range(n)] inter = [[None for i in range(n)] for j in range(n)] for i in range(n): # to the the sam index intra[i][i] = csc(h.intra) inter[i][i] = csc(h.ty) for i in range(n - 1): # one more or less intra[i][i + 1] = csc(h.tx) intra[i + 1][i] = csc(h.tx.H) inter[i + 1][i] = csc(h.txmy.H) inter[i][i + 1] = csc(h.txy) ho.intra = bmat(intra).todense() ho.inter = bmat(inter).todense() return ho
def onsite_supercell(h,nsuper,mc=None): if h.dimensionality!=2: return NotImplemented inds = [] k = 0 n = nsuper*nsuper # number of cells intrasuper = [[None for j in range(n)] for i in range(n)] for i in range(nsuper): for j in range(nsuper): inds += [(i,j)] k += 1 from scipy.sparse import bmat from scipy.sparse import csc_matrix as csc tx = csc(h.tx) ty = csc(h.ty) txy = csc(h.txy) txmy = csc(h.txmy) intra = csc(h.intra) if mc is None: mc = intra else: mc = csc(mc) for i in range(n): intrasuper[i][i] = intra # intracell (x1,y1) = inds[i] for j in range(n): (x2,y2) = inds[j] dx = x2-x1 dy = y2-y1 if dx==1 and dy==0: intrasuper[i][j] = tx if dx==-1 and dy==0: intrasuper[i][j] = tx.H if dx==0 and dy==1: intrasuper[i][j] = ty if dx==0 and dy==-1: intrasuper[i][j] = ty.H if dx==1 and dy==1: intrasuper[i][j] = txy if dx==-1 and dy==-1: intrasuper[i][j] = txy.H if dx==1 and dy==-1: intrasuper[i][j] = txmy if dx==-1 and dy==1: intrasuper[i][j] = txmy.H if nsuper%2==1: # central cell ii=int(n/2) intrasuper[ii][ii] = mc # central onsite else: ii=int(n/2) ii = ii - int(nsuper/2) intrasuper[ii][ii] = mc # central onsite intrasuper = bmat(intrasuper).todense() # supercell return intrasuper
def hamiltonian_bulk2ribbon(h, n=10, sparse=False, check=True): """Converts a hexagonal bulk hamiltonian into a ribbon hamiltonian""" from scipy.sparse import csc_matrix as csc from scipy.sparse import bmat go = h.geometry.copy() # copy geometry ho = h.copy() # copy hamiltonian if np.abs(go.a1.dot(go.a2)) > 0.01: if check: raise # if axis non orthogonal ho.dimensionality = 1 # reduce dimensionality ho.geometry.dimensionality = 1 # reduce dimensionality intra = [[None for i in range(n)] for j in range(n)] inter = [[None for i in range(n)] for j in range(n)] for i in range(n): # to the the sam index intra[i][i] = csc(h.intra) inter[i][i] = csc(h.tx) for i in range(n - 1): # one more or less intra[i][i + 1] = csc(h.ty) intra[i + 1][i] = csc(h.ty.H) inter[i + 1][i] = csc(h.txmy) inter[i][i + 1] = csc(h.txy) if sparse: ho.intra = bmat(intra) ho.inter = bmat(inter) ho.is_sparse = True # hamiltonian is sparse else: ho.intra = bmat(intra).todense() ho.inter = bmat(inter).todense() # calculate the angle import sculpt go = sculpt.rotate_a2b(go, go.a1, np.array([1., 0., 0.])) ho.geometry.celldis = go.a1[0] # first eigenvector r = [] for i in range(n): for ri in go.r: r.append(ri + i * go.a2) ho.geometry.r = np.array(r) ho.geometry.r2xyz() # get r positions ho.geometry.center() ho.dimensionality = 1 # for geometries with names if ho.geometry.atoms_have_names: ho.geometry.atoms_names = ho.geometry.atoms_names * n return ho
def hamiltonian_bulk2ribbon(h, n=10, sparse=False, check=True): """Converts a hexagonal bulk hamiltonian into a ribbon hamiltonian""" from scipy.sparse import csc_matrix as csc from scipy.sparse import bmat go = h.geometry.copy() # copy geometry ho = h.copy() # copy hamiltonian # if np.abs(go.a1.dot(go.a2))>0.01: # if check: raise # if axis non orthogonal ho.dimensionality = 1 # reduce dimensionality ho.geometry.dimensionality = 1 # reduce dimensionality intra = [[None for i in range(n)] for j in range(n)] inter = [[None for i in range(n)] for j in range(n)] for i in range(n): # to the the sam index intra[i][i] = csc(h.intra) inter[i][i] = csc(h.tx) for i in range(n - 1): # one more or less intra[i][i + 1] = csc(h.ty) intra[i + 1][i] = csc(h.ty.H) inter[i + 1][i] = csc(h.txmy) inter[i][i + 1] = csc(h.txy) if sparse: ho.intra = bmat(intra) ho.inter = bmat(inter) ho.is_sparse = True # hamiltonian is sparse else: ho.intra = bmat(intra).todense() ho.inter = bmat(inter).todense() # calculate the angle import sculpt ho.geometry = sculpt.rotate_a2b(ho.geometry, ho.geometry.a1, np.array([1., 0., 0.])) ho.geometry = h.geometry.supercell((1, n)) # create supercell ho.geometry.dimensionality = 1 ho.geometry.a1 = h.geometry.a1 # add the unit cell vector ho.dimensionality = 1 # for geometries with names if ho.geometry.atoms_have_names: ho.geometry.atoms_names = ho.geometry.atoms_names * n return ho
def honeycomb2squareMoS2(h): """Transforms a honeycomb lattice into a square lattice""" ho = deepcopy(h) # output geometry g = h.geometry # geometry go = deepcopy(g) # output geometry go.a1 = g.a1 + g.a2 go.a2 = g.a1 - g.a2 go.r = np.concatenate([g.r, g.r + g.a1]) go.r2xyz() # update r atribbute zero = csc(h.tx * 0.) # define sparse intra = csc(h.intra) tx = csc(h.tx) ty = csc(h.ty) txy = csc(h.txy) txmy = csc(h.txmy) # define new hoppings ho.intra = bmat([[intra, tx], [tx.H, intra]]).todense() ho.tx = bmat([[txy, zero], [ty, txy]]).todense() ho.ty = bmat([[txmy, zero], [ty.H, txmy]]).todense() ho.txy = bmat([[zero, zero], [tx, zero]]).todense() ho.txmy = bmat([[zero, zero], [zero, zero]]).todense() ho.geometry = go return ho
def index(h, n=[0]): """Return a projector onto a site""" num = len(h.geometry.r) val = [1. for i in n] m = csc((val, (n, n)), shape=(num, num), dtype=np.complex) return h.spinless2full(m) # return matrix
def mono2bi(m): """Increase the size of the matrices""" return bmat([[csc(m), None], [None, csc(m)]]).todense()
def mono2tri(m): """Increase the size of the matrices""" mo = [[None for i in range(3)] for j in range(3)] for i in range(3): mo[i][i] = csc(m) return bmat(mo).todense()
def mono2bi(m): """Increase the size of the matrices""" if h.is_sparse: return bmat([[csc(m), None], [None, csc(m)]]) else: return bmat([[csc(m), None], [None, csc(m)]]).todense()
def read_supercell_hamiltonian(input_file="hr_truncated.dat", is_real=False, nsuper=1): """Reads an output hamiltonian for a supercell from wannier""" mt = np.genfromtxt(input_file) # get file m = mt.transpose() # transpose matrix # read the hamiltonian matrices class Hopping: pass # create empty class tlist = [] def get_t(i, j, k): norb = np.max([np.max(np.abs(m[3])), np.max(np.abs(m[4]))]) mo = np.matrix(np.zeros((norb, norb), dtype=np.complex)) for l in mt: # look into the file if i == int(l[0]) and j == int(l[1]) and k == int(l[2]): if is_real: mo[int(l[3]) - 1, int(l[4]) - 1] = l[5] # store element else: mo[int(l[3]) - 1, int(l[4]) - 1] = l[5] + 1j * l[6] # store element return mo # return the matrix # the previous is not used yet... g = geometry.kagome_lattice() # create geometry h = g.get_hamiltonian() # build hamiltonian nstot = nsuper**2 intra = [[None for i in range(nstot)] for j in range(nstot)] tx = [[None for i in range(nstot)] for j in range(nstot)] ty = [[None for i in range(nstot)] for j in range(nstot)] txy = [[None for i in range(nstot)] for j in range(nstot)] txmy = [[None for i in range(nstot)] for j in range(nstot)] from scipy.sparse import csc_matrix as csc vecs = [] # create the identifacion vectors inds = [] acu = 0 for i in range(nsuper): # loop over first replica for j in range(nsuper): # loop over second replica vecs.append(np.array([i, j])) # append vector inds.append(acu) acu += 1 # increase counter for i in inds: # loop over first vector for j in inds: # loop over second vector v1 = vecs[i] v2 = vecs[j] dv = v1 - v2 # difference in vector intra[i][j] = csc(get_t(dv[0], dv[1], 0)) tx[i][j] = csc(get_t(dv[0] + 1, dv[1], 0)) ty[i][j] = csc(get_t(dv[0], dv[1] + 1, 0)) txy[i][j] = csc(get_t(dv[0] + 1, dv[1] + 1, 0)) txmy[i][j] = csc(get_t(dv[0] + 1, dv[1] - 1, 0)) h.intra = bmat(intra).todense() h.tx = bmat(tx).todense() h.ty = bmat(tx).todense() h.txy = bmat(txy).todense() h.txmy = bmat(txmy).todense() h.geometry = read_geometry() # read the geometry of the system h.geometry = h.geometry.supercell(nsuper) # create supercell if len(h.geometry.r) != len(h.intra): print "Dimensions do not match", len(g.r), len(h.intra) print h.geometry.r raise # error if dimensions dont match return h
def get_eigenvectors(h, nk=10, kpoints=False, k=None, sparse=False, numw=None): from scipy.sparse import csc_matrix as csc shape = h.intra.shape if numw is not None: sparse = True if h.dimensionality == 0: vv = algebra.eigh(h.intra) vecs = [v for v in vv[1].transpose()] if kpoints: return vv[0], vecs, [[0., 0., 0.] for e in vv[0]] else: return vv[0], vecs elif h.dimensionality > 0: f = h.get_hk_gen() if k is None: kp = kmesh(h.dimensionality, nk=nk) # generate a mesh else: kp = np.array([k]) # kpoint given on input # vvs = [lg.eigh(f(k)) for k in kp] # diagonalize k hamiltonian nkp = len(kp) # total number of k-points if sparse: # sparse Hamiltonians fk = lambda k: slg.eigsh( csc(f(k)), k=numw, which="LM", sigma=0.0, tol=1e-5) vvs = parallel.pcall(fk, kp) else: # dense Hamiltonians if parallel.cores > 1: # in parallel # vvs = parallel.multieigh([f(k) for k in kp]) # multidiagonalization vvs = parallel.pcall(lambda k: algebra.eigh(f(k)), kp) else: vvs = [algebra.eigh(f(k)) for k in kp] # nume = sum([len(v[0]) for v in vvs]) # number of eigenvalues calculated eigvecs = np.zeros((nume, h.intra.shape[0]), dtype=np.complex) # eigenvectors eigvals = np.zeros(nume) # eigenvalues #### New way #### # eigvals = np.array([iv[0] for iv in vvs]).reshape(nkp*shape[0],order="F") # eigvecs = np.array([iv[1].transpose() for iv in vvs]).reshape((nkp*shape[0],shape[1]),order="F") # if kpoints: # return also the kpoints # kvectors = [] # empty list # for ik in kp: # for i in range(h.intra.shape[0]): kvectors.append(ik) # store # return eigvals,eigvecs,kvectors # else: # return eigvals,eigvecs #### Old way, slightly slower but clearer #### iv = 0 kvectors = [] # empty list for ik in range(len(kp)): # loop over kpoints vv = vvs[ik] # get eigenvalues and eigenvectors for (e, v) in zip(vv[0], vv[1].transpose()): eigvecs[iv] = v.copy() eigvals[iv] = e.copy() kvectors.append(kp[ik]) iv += 1 if kpoints: # return also the kpoints # for iik in range(len(kp)): # ik = kp[iik] # store kpoint # for e in vvs[iik][0]: kvectors.append(ik) # store return eigvals, eigvecs, kvectors else: return eigvals, eigvecs else: raise
def read_supercell_hamiltonian(input_file="hr_truncated.dat", is_real=False, nsuper=1): """Reads an output hamiltonian for a supercell from wannier""" mt = np.genfromtxt(input_file) # get file m = mt.transpose() # transpose matrix # read the hamiltonian matrices class Hopping: pass # create empty class tlist = [] def get_t(i, j, k): norb = int(np.max([np.max(np.abs(m[3])), np.max(np.abs(m[4]))])) mo = np.matrix(np.zeros((norb, norb), dtype=np.complex)) for l in mt: # look into the file if i == int(l[0]) and j == int(l[1]) and k == int(l[2]): if is_real: mo[int(l[3]) - 1, int(l[4]) - 1] = l[5] # store element else: mo[int(l[3]) - 1, int(l[4]) - 1] = l[5] + 1j * l[6] # store element return mo # return the matrix # this function will be called in a loop g = geometry.kagome_lattice() # create geometry h = g.get_hamiltonian() # build hamiltonian h.has_spin = False nstot = nsuper**2 intra = [[None for i in range(nstot)] for j in range(nstot)] tx = [[None for i in range(nstot)] for j in range(nstot)] ty = [[None for i in range(nstot)] for j in range(nstot)] txy = [[None for i in range(nstot)] for j in range(nstot)] txmy = [[None for i in range(nstot)] for j in range(nstot)] from scipy.sparse import csc_matrix as csc vecs = [] # create the identifacion vectors inds = [] acu = 0 try: # read different supercells nsuperx = nsuper[0] nsupery = nsuper[1] nsuperz = nsuper[2] except: # read different supercells nsuperx = nsuper nsupery = nsuper nsuperz = nsuper for i in range(nsuperx): # loop over first replica for j in range(nsupery): # loop over second replica vecs.append(np.array([i, j])) # append vector inds.append(acu) acu += 1 # add one to the accumulator for i in inds: # loop over first vector for j in inds: # loop over second vector v1 = vecs[i] # position of i esim cell v2 = vecs[j] # position of j esim cell dv = v2 - v1 # difference in vector # get the different block elements intra[i][j] = csc(get_t(dv[0], dv[1], 0)) tx[i][j] = csc(get_t(dv[0] + nsuper, dv[1], 0)) ty[i][j] = csc(get_t(dv[0], dv[1] + nsuper, 0)) txy[i][j] = csc(get_t(dv[0] + nsuper, dv[1] + nsuper, 0)) txmy[i][j] = csc(get_t(dv[0] + nsuper, dv[1] - nsuper, 0)) h.intra = bmat(intra).todense() h.tx = bmat(tx).todense() h.ty = bmat(ty).todense() h.txy = bmat(txy).todense() h.txmy = bmat(txmy).todense() h.geometry = read_geometry() # read the geometry of the system if nsuper > 1: h.geometry = h.geometry.supercell(nsuper) # create supercell if len(h.geometry.r) != len(h.intra): print("Dimensions do not match", len(g.r), len(h.intra)) print(h.geometry.r) # raise # error if dimensions dont match # names of the orbitals h.orbitals = get_all_orbitals() * nsuper**2 return h
string.rstrip, reflists ) #Python's rstrip() method strips all kinds of trailing whitespace by default curr_item = reflists[0] reflists = reflists[1:] for item in reflists: if item in paperIdInd: rowList.append(paperIdInd[curr_item]) columnList.append(paperIdInd[item]) valueList.append(1) row += 1 #Create a sparse csc matrix strucSpMat = csc( (np.array(valueList), (np.array(rowList), np.array(columnList))), shape=(len(df_paperId), len(df_paperId))) strucSpMat_org = strucSpMat print 'Processing structure ended' #%% #Processing the content print 'Processing content started' C = pd.read_csv(filepath + contentFile, header=None) C = C.as_matrix(columns=None) true_labels = pd.read_csv(filepath + fileLabels, header=None)