def kdos_bands(h, use_kpm=True, kpath=None, scale=10.0, ewindow=4.0, ne=1000, delta=0.01, ntries=10): """Calculate the KDOS bands using the KPM""" if not use_kpm: raise # nope hkgen = h.get_hk_gen() # get generator if kpath is None: kpath = klist.default(h.geometry) # default fo = open("KDOS_BANDS.OUT", "w") # open file ik = 0 tr = timing.Testimator("KDOS") # generate object for k in kpath: # loop over kpoints tr.remaining(ik, len(kpath)) hk = hkgen(k) # get Hamiltonian npol = int(scale / delta) # number of polynomials (x, y) = kpm.tdos(hk, scale=scale, npol=npol, ne=ne, ewindow=ewindow, ntries=ntries) # compute for (ix, iy) in zip(x, y): # loop fo.write(str(ik / len(kpath)) + " ") fo.write(str(ix) + " ") fo.write(str(iy) + "\n") fo.flush() ik += 1 fo.close()
def density(h, e=0.0, nk=20, mode="arpack", random=True, num_wf=20, window=0.1, nrep=3, name="DENSITY_UP.OUT", window_mode="around", kpoints=None): """ Calculate the electronic density""" if h.intra.shape[0] < 100: mode = "full" if h.dimensionality == 0: nk = 1 # single kpoint hkgen = h.get_hk_gen() # get generator d = np.zeros(h.intra.shape[0]) # initialize tr = timing.Testimator("DENSITY") if kpoints is None: kpoints = [np.random.random(3) for ik in range(nk)] else: nk = len(kpoints) # given at input for ik in range(len(kpoints)): tr.remaining(ik, nk) k = kpoints[ik] # random k-point hk = csc_matrix(hkgen(k)) # get Hamiltonian d = d + restricted_density(hk, n=num_wf, e=e, window=window, mode=mode, window_mode=window_mode) d /= nk # normalize d = spatial_density(h, d) # sum if necessary geometry.write_profile(h.geometry, d, name=name, nrep=nrep) return d # return density
def dos_kpm(h, scale=10.0, ewindow=4.0, ne=1000, delta=0.01, ntries=10, nk=100): """Calculate the KDOS bands using the KPM""" hkgen = h.get_hk_gen() # get generator tr = timing.Testimator("DOS") # generate object if h.dimensionality == 0: nk = 0 # single kpoint ytot = np.zeros(ne) # initialize for ik in range(nk): # loop over kpoints tr.remaining(ik, nk) hk = hkgen(np.random.random(3)) # get Hamiltonian npol = int(scale / delta) # number of polynomials (x, y) = kpm.tdos(hk, scale=scale, npol=npol, ne=ne, ewindow=ewindow, ntries=ntries) # compute ytot += y # add contribution ytot /= nk # normalize np.savetxt("DOS.OUT", np.matrix([x, ytot]).T) # save in file
def calculate_dos_hkgen(hkgen, ks, ndos=100, delta=None, is_sparse=False, numw=10): """Calculate density of states using the ks given on input""" es = np.zeros((len(ks), hkgen(ks[0]).shape[0])) # empty list es = [] # empty list tr = timing.Testimator("DOS") for ik in range(len(ks)): tr.remaining(ik, len(ks)) hk = hkgen(ks[ik]) # Hamiltonian t0 = time.clock() # time if is_sparse: # sparse Hamiltonian es += [smalleig(hk, numw=numw)] # eigenvalues else: # dense Hamiltonian es += [lg.eigvalsh(hk)] # get eigenvalues # es = es.reshape(len(es)*len(es[0])) # 1d array es = np.array(es) # convert to array nk = len(ks) # number of kpoints if delta is None: delta = 5. / nk # automatic delta xs = np.linspace(np.min(es) - .5, np.max(es) + .5, ndos) # create x ys = calculate_dos(es, xs, delta) # use the Fortran routine ys /= nk # normalize write_dos(xs, ys) # write in file print("\nDOS finished")
def write_berry(h, kpath=None, dk=0.01, window=None, max_waves=None, mode="Wilson", delta=0.001, reciprocal=False, operator=None): """Calculate and write in file the Berry curvature""" if kpath is None: kpath = klist.default(h.geometry) # take default kpath fo = open("BERRY_CURVATURE.OUT", "w") # open file tr = timing.Testimator("BERRY CURVATURE") ik = 0 if operator is not None: mode = "Green" # Green function mode for k in kpath: tr.remaining(ik, len(kpath)) if reciprocal: k = h.geometry.get_k2K_generator()(k) # convert ik += 1 if mode == "Wilson": b = berry_curvature(h, k, dk=dk, window=window, max_waves=max_waves) if mode == "Green": f = h.get_gk_gen(delta=delta) # get generator b = berry_green(f, k=k, operator=operator) fo.write(str(k[0]) + " ") fo.write(str(k[1]) + " ") fo.write(str(b) + "\n") fo.flush() fo.close() # close file
def interface(h1, h2, energies=np.linspace(-1., 1., 100), operator=None, delta=0.01, kpath=None): """Get the surface DOS of an interface""" from scipy.sparse import csc_matrix, bmat if kpath is None: if h1.dimensionality == 3: g2d = h1.geometry.copy() # copy Hamiltonian import sculpt g2d = sculpt.set_xy_plane(g2d) kpath = klist.default(g2d, nk=100) elif h1.dimensionality == 2: kpath = [[k, 0., 0.] for k in np.linspace(0., 1., 40)] else: raise fo = open("KDOS_INTERFACE.OUT", "w") fo.write("# k, E, Bulk1, Surf1, Bulk2, Surf2, interface\n") tr = timing.Testimator("KDOS") # generate object ik = 0 h1 = h1.get_multicell() # multicell Hamiltonian h2 = h2.get_multicell() # multicell Hamiltonian for k in kpath: tr.remaining(ik, len(kpath)) # generate object ik += 1 # for energy in energies: # (b1,s1,b2,s2,b12) = green.interface(h1,h2,k=k,energy=energy,delta=delta) # out = green.interface(h1,h2,k=k,energy=energy,delta=delta) outs = green.interface_multienergy(h1, h2, k=k, energies=energies, delta=delta) for (energy, out) in zip(energies, outs): if operator is None: op = np.identity(h1.intra.shape[0] * 2) # normal cell ops = np.identity(h1.intra.shape[0]) # supercell # elif callable(operator): op = callable(op) else: op = operator # normal cell ops = bmat([[csc_matrix(operator), None], [None, csc_matrix(operator)]]) # write everything fo.write(str(ik) + " " + str(energy) + " ") for g in out: # loop if g.shape[0] == op.shape[0]: d = -(g * op).trace()[0, 0].imag # bulk else: d = -(g * ops).trace()[0, 0].imag # interface fo.write(str(d) + " ") fo.write("\n") fo.flush() # flush fo.close()
def get_bands_1d(h, nkpoints=100, operator=None, num_bands=None, callback=None): if num_bands is None: # all the bands if operator is not None: diagf = lg.eigh # all eigenvals and eigenfuncs else: diagf = lg.eigvalsh # all eigenvals and eigenfuncs else: # using arpack h = h.copy() h.turn_sparse() # sparse Hamiltonian def diagf(m): eig, eigvec = slg.eigsh(m, k=num_bands, which="LM", sigma=0.0, tol=arpack_tol, maxiter=arpack_maxiter) if operator is None: return eig else: return (eig, eigvec) hkgen = h.get_hk_gen() # generator hamiltonian ks = np.linspace(0., 1., nkpoints, endpoint=True) f = open("BANDS.OUT", "w") # open bands file f.write("# system_dimension = 1\n") # if operator is not None: operator=np.matrix(operator) # convert to matrix tr = timing.Testimator("BANDSTRUCTURE") # generate object ik = 0 for k in ks: # loop over kpoints ik += 1 tr.remaining(ik, ks.shape[0]) hk = hkgen(k) # get hamiltonian # if h.is_sparse: hk = hk.todense() # turn the matrix dense if operator is None: es = diagf(hk) for e in es: # loop over energies f.write(str(k) + " " + str(e) + "\n") # write in file if callback is not None: callback(k, es) # call the function else: es, ws = diagf(hk) ws = ws.transpose() # transpose eigenvectors for (e, w) in zip(es, ws): # loop over waves if callable(operator): waw = operator(w, k=k) else: waw = braket_wAw( w, operator).real # calcualte expectation value f.write(str(k) + " " + str(e) + " " + str(waw) + "\n") # write in file if callback is not None: callback(k, es, ws) # call the function f.close() return np.genfromtxt("BANDS.OUT").transpose() # return data
def dos2d(h, use_kpm=False, scale=10., nk=100, ntries=1, delta=None, ndos=500, numw=20, random=True, kpm_window=1.0): """ Calculate density of states of a 2d system""" if h.dimensionality != 2: raise # only for 2d ks = [] from klist import kmesh ks = kmesh(h.dimensionality, nk=nk) if random: ks = [np.random.random(2) for ik in ks] print("Random k-mesh") if not use_kpm: # conventional method hkgen = h.get_hk_gen() # get generator if delta is None: delta = 6. / nk # conventiona algorithm calculate_dos_hkgen(hkgen, ks, ndos=ndos, delta=delta, is_sparse=h.is_sparse, numw=numw) else: # use the kpm npol = ndos // 10 h.turn_sparse() # turn the hamiltonian sparse hkgen = h.get_hk_gen() # get generator mus = np.array([0.0j for i in range(2 * npol)]) # initialize polynomials import kpm tr = timing.Testimator("DOS") ik = 0 for k in ks: # loop over kpoints # print("KPM DOS at k-point",k) ik += 1 tr.remaining(ik, len(ks)) if random: kr = np.random.random(2) print("Random sampling in DOS") hk = hkgen(kr) # hamiltonian else: hk = hkgen(k) # hamiltonian mus += kpm.random_trace(hk / scale, ntries=ntries, n=npol) mus /= len(ks) # normalize by the number of kpoints xs = np.linspace(-0.9, 0.9, ndos) * kpm_window # x points ys = kpm.generate_profile(mus, xs) # generate the profile write_dos(xs * scale, ys) # write in file return (xs, ys)
def eigenvalues(h, nk): """Return all the eigenvalues of a Hamiltonian""" import klist h.turn_dense() ks = klist.kmesh(h.dimensionality, nk=nk) # get grid hkgen = h.get_hk_gen() # get generator e0 = 0.0 import timing est = timing.Testimator(maxite=len(ks)) for k in ks: # loop est.iterate() es = eigvalsh(hkgen(k)).tolist() # add e0 += np.sum(es[es < 0.]) # add contribution return e0 / len(ks) # return the ground state energy
def surface(h1, energies=np.linspace(-1., 1., 100), operator=None, delta=0.01, kpath=None, hs=None): """Get the surface DOS of an interface""" from scipy.sparse import csc_matrix, bmat if kpath is None: if h1.dimensionality == 3: g2d = h1.geometry.copy() # copy Hamiltonian import sculpt g2d = sculpt.set_xy_plane(g2d) kpath = klist.default(g2d, nk=100) elif h1.dimensionality == 2: kpath = [[k, 0., 0.] for k in np.linspace(0., 1., 40)] else: raise fo = open("KDOS.OUT", "w") fo.write("# k, E, Surface, Bulk\n") tr = timing.Testimator("KDOS") # generate object ik = 0 h1 = h1.get_multicell() # multicell Hamiltonian for k in kpath: tr.remaining(ik, len(kpath)) # generate object ik += 1 outs = green.surface_multienergy(h1, k=k, energies=energies, delta=delta, hs=hs) for (energy, out) in zip(energies, outs): # write everything fo.write(str(ik) + " " + str(energy) + " ") for g in out: # loop if operator is None: d = -g.trace()[0, 0].imag # only the trace elif callable(operator): d = operator(g, k=k) # call the operator else: d = -(g * operator).trace()[0, 0].imag # assume it is a matrix fo.write(str(d) + " ") # write in a file fo.write("\n") # next line fo.flush() # flush fo.close()
def dos1d(h, use_kpm=False, scale=10., nk=100, npol=100, ntries=2, ndos=1000, delta=0.01, ewindow=None, frand=None): """ Calculate density of states of a 1d system""" if h.dimensionality != 1: raise # only for 1d ks = np.linspace(0., 1., nk, endpoint=False) # number of kpoints if not use_kpm: # conventional method hkgen = h.get_hk_gen() # get generator # delta = 16./(nk*h.intra.shape[0]) # smoothing calculate_dos_hkgen(hkgen, ks, ndos=ndos, delta=delta) # conventiona algorithm else: h.turn_sparse() # turn the hamiltonian sparse hkgen = h.get_hk_gen() # get generator yt = np.zeros(ndos) # number of dos import kpm ts = timing.Testimator("DOS") for i in range(nk): # loop over kpoints k = np.random.random(3) # random k-point hk = hkgen(k) # hamiltonian (xs, yi) = kpm.tdos(hk, scale=scale, npol=npol, frand=frand, ewindow=ewindow, ntries=ntries, ne=ndos) yt += yi # Add contribution ts.remaining(i, nk) yt /= nk # normalize write_dos(xs, yt) # write in file print() return xs, yt
def chern(h, dk=-1, nk=10, delta=0.0001, mode="Wilson", operator=None): """ Calculates the chern number of a 2d system """ c = 0.0 ks = [] # array for kpoints bs = [] # array for berrys if dk < 0: dk = 1. / float(2 * nk) # automatic dk if operator is not None and mode == "Wilson": print("Swuitching to Green mode in topology") mode = "Green" # create the function def fberry(k): # function to integrate if mode == "Wilson": return berry_curvature(h, k, dk=dk) if mode == "Green": f2 = h.get_gk_gen(delta=delta) # get generator return berry_green(f2, k=[k[0], k[1], 0.], operator=operator) ################## for x in np.linspace(0., 1., nk, endpoint=False): for y in np.linspace(0., 1., nk, endpoint=False): ks.append([x, y]) # create kpoints tr = timing.Testimator("CHERN NUMBER") ik = 0 for k in ks: # loop tr.remaining(ik, len(ks)) ik += 1 # increase b = fberry(k) # get berry curvature bs.append(b) # write in file fo = open("BERRY_CURVATURE.OUT", "w") # open file for (k, b) in zip(ks, bs): fo.write(str(k[0]) + " ") fo.write(str(k[1]) + " ") fo.write(str(b) + "\n") fo.close() # close file ################ c = sum(bs) # sum berry curvatures c = c / (2. * np.pi * nk * nk) open("CHERN.OUT", "w").write(str(c) + "\n") return c
def bulkandsurface(h1, energies=np.linspace(-1., 1., 100), operator=None, delta=0.01, hs=None, nk=30): """Compute the DOS of the bulk and the surface""" tr = timing.Testimator("KDOS") # generate object ik = 0 h1 = h1.get_multicell() # multicell Hamiltonian kpath = [np.random.random(3) for i in range(nk)] # loop dosout = np.zeros((2, len(energies))) # output DOS for k in kpath: tr.remaining(ik, len(kpath)) # generate object ik += 1 outs = green.surface_multienergy(h1, k=k, energies=energies, delta=delta, hs=hs) ie = 0 for (energy, out) in zip(energies, outs): # loop over energies # compute dos ig = 0 for g in out: # loop if operator is None: d = -g.trace()[0, 0].imag # only the trace elif callable(operator): d = operator(g, k=k) # call the operator else: d = -(g * operator).trace()[0, 0].imag # assume it is a matrix dosout[ig, ie] += d # store ig += 1 # increase site ie += 1 # increase energy # write in file dosout /= nk # normalize np.savetxt("DOS_BULK_SURFACE.OUT", np.matrix([energies, dosout[0], dosout[1]]).T)
def berry_map(h, dk=-1, nk=40, reciprocal=True, nsuper=1, window=None, max_waves=None, mode="Wilson", delta=0.001, operator=None): """ Calculates the chern number of a 2d system """ if operator is not None: mode = "Green" # Green function mode c = 0.0 ks = [] # array for kpoints if dk < 0: dk = 5. / float(2 * nk) # automatic dk if reciprocal: R = h.geometry.get_k2K() else: R = np.matrix(np.identity(3)) fo = open("BERRY_MAP.OUT", "w") # open file nt = nk * nk # total number of points tr = timing.Testimator("BERRY CURVATURE") ik = 0 for x in np.linspace(-nsuper, nsuper, nk, endpoint=False): for y in np.linspace(-nsuper, nsuper, nk, endpoint=False): tr.remaining(ik, nt) ik += 1 r = np.matrix([x, y, 0.]).T # real space vectors k = np.array((R * r).T)[0] # change of basis if mode == "Wilson": b = berry_curvature(h, k, dk=dk, window=window, max_waves=max_waves) if mode == "Green": f = h.get_gk_gen(delta=delta) # get generator b = berry_green(f, k=k, operator=operator) fo.write(str(x) + " " + str(y) + " " + str(b) + "\n") fo.flush() fo.close() # close file
def get_bands_2d(h, kpath=None, operator=None, num_bands=None, callback=None, central_energy=0.0): """Get a 2d bandstructure""" if num_bands is None: # all the bands if operator is not None: def diagf(m): # diagonalization routine if h.is_sparse and h.intra.shape[0] < maxdim: return lg.eigh(m.todense()) # all eigenvals and eigenfuncs else: return lg.eigh(m) # all eigenvals and eigenfuncs else: def diagf(m): # diagonalization routine if h.is_sparse and h.intra.shape[0] < maxdim: return lg.eigvalsh( m.todense()) # all eigenvals and eigenfuncs else: return lg.eigvalsh(m) # all eigenvals and eigenfuncs else: # using arpack h = h.copy() h.turn_sparse() # sparse Hamiltonian def diagf(m): eig, eigvec = slg.eigsh(m, k=num_bands, which="LM", sigma=central_energy, tol=arpack_tol, maxiter=arpack_maxiter) if operator is None: return eig else: return (eig, eigvec) # open file and get generator f = open("BANDS.OUT", "w") # open bands file hkgen = h.get_hk_gen() # generator hamiltonian if kpath is None: import klist kpath = klist.default(h.geometry) # generate default klist tr = timing.Testimator("BANDSTRUCTURE") # generate object for k in range(len(kpath)): # loop over kpoints # print("Bands in kpoint",k,"of",len(kpath),end="\r") tr.remaining(k, len(kpath)) hk = hkgen(kpath[k]) # get hamiltonian if operator is None: es = diagf(hk) for e in es: # loop over energies f.write(str(k) + " " + str(e) + "\n") # write in file if callback is not None: callback(k, es) # call the function else: es, ws = diagf(hk) ws = ws.transpose() # transpose eigenvectors for (e, w) in zip(es, ws): # loop over waves if callable(operator): try: waw = operator(w, k=kpath[k]) # call the operator except: print("Check out the k optional argument in operator") waw = operator(w) # call the operator else: waw = braket_wAw( w, operator).real # calculate expectation value f.write(str(k) + " " + str(e) + " " + str(waw) + "\n") # write in file # callback function in each iteration if callback is not None: callback(k, es, ws) # call the function f.flush() f.close() print("\nBANDS finished") return np.genfromtxt("BANDS.OUT").transpose() # return data