def get_band_energies(self, kpts=None, shift=True, rs='kappa', h1=False): ''' Return band energies for explicitly given list of k-points. parameters: =========== kpts: list of k-points; e.g. kpts=[(0,0,0),(pi/2,0,0),(pi,0,0)] k- or kappa-points, depending on parameter rs. if None, return for all k-points in the calculation shift: shift zero to the Fermi-level rs: use 'kappa'- or 'k'-points in reciprocal space h1: Add Coulomb part to hamiltonian matrix. Required for consistent use of SCC. ''' if kpts == None: e = self.st.e * Hartree else: if rs == 'k': klist = k_to_kappa_points(kpts, self.el.atoms) elif rs == 'kappa': klist = kpts e = self.st.get_band_energies(klist, h1) * Hartree if shift: return e - self.get_fermi_level() else: return e
def get_band_energies(self, kpts=None, shift=True, rs="kappa", h1=False): """ Return band energies for explicitly given list of k-points. parameters: =========== kpts: list of k-points; e.g. kpts=[(0,0,0),(pi/2,0,0),(pi,0,0)] k- or kappa-points, depending on parameter rs. if None, return for all k-points in the calculation shift: shift zero to the Fermi-level rs: use 'kappa'- or 'k'-points in reciprocal space h1: Add Coulomb part to hamiltonian matrix. Required for consistent use of SCC. """ if kpts == None: e = self.st.e * Hartree else: if rs == "k": klist = k_to_kappa_points(kpts, self.el.atoms) elif rs == "kappa": klist = kpts e = self.st.get_band_energies(klist, h1) * Hartree if shift: return e - self.get_fermi_level() else: return e
def setup_k_sampling(self,kpts,physical=True,rs='kappa'): ''' Setup the k-point sampling and their weights. @param kpts: 3-tuple: number of k-points in different directions list of 3-tuples: k-points given explicitly @param physical: No meaning for infinite periodicities. For physically periodic systems only certain number of k-points are allowed. (like wedge of angle 2*pi/N, only number of k-points that divides N, is physically allowed). If physical=False, allow interpolation of this k-sampling. rs: use 'kappa'- or 'k'-point sampling ''' if (len(kpts)==1 or isinstance(kpts,tuple) and kpts!=(1,1,1)) and self.calc.get('width')<1E-10: raise AssertionError('With k-point sampling width must be>0!') M = self.calc.el.get_number_of_transformations() if isinstance(kpts,tuple): table = self.calc.el.atoms.container.get_table() # set up equal-weighted and spaced k-point mesh if 0 in kpts: raise AssertionError('Each direction must have at least one k-point! (Gamma-point)') kl=[] for i in range(3): if M[i]==np.Inf: # arbitrary sampling is allowed spacing = 2*pi/kpts[i] kl.append( np.linspace(-pi+spacing/2,pi-spacing/2,kpts[i]) ) else: # TODO: choose the closest number of k-points if # sampling should be physical # first calculate possible numer of k-points, then # select the ones closest to the desired one # nks = M/divisors(M) # nk1 = nks[abs(nks-nk).argmin()] # discrete, well-defined sampling; any k-point is not allowed if kpts[i] not in mix.divisors(M[i]) and physical: print 'Allowed k-points for direction',i,'are',mix.divisors(M[i]) raise Warning('Non-physical k-point sampling! ') else: kl.append( np.linspace(0,2*pi-2*pi/kpts[i],kpts[i]) ) k=[] wk=[] kpt_indices = [] nk0 = np.prod(kpts) for a in range(kpts[0]): for b in range(kpts[1]): for c in range(kpts[2]): newk = np.array([kl[0][a], kl[1][b], kl[2][c]]) newind = (a,b,c) one_equivalent = False for i in range(3): if 'equivalent' in table[i]: if one_equivalent: raise NotImplementedError('Surprising type of new symmetry; reconsider implementation.') one_equivalent = True n = table[i]['equivalent'] # symmetry op i is equivalent to tuple n assert n[i]==0 newk[i] = newk[i] + 1.0*np.dot(n,newk)/M[i] inv_exists = False # if newk's inverse exists, increase its weight by default for ik, oldk in enumerate(k): if np.linalg.norm(oldk+newk)<1E-10: inv_exists = True wk[ik]+=1.0/nk0 # newk's inverse does not exist; make new k-point if not inv_exists: k.append( newk ) wk.append( 1.0/nk0 ) kpt_indices.append( newind ) nk=len(k) k=np.array(k) wk=np.array(wk) else: # work with a given set of k-points nk=len(kpts) if rs=='k': k = k_to_kappa_points(kpts,self.calc.el.atoms) else: k=np.array(kpts) wk=np.ones(nk)/nk kl=None kpt_indices=[] # now sampling is set up. Check consistency. pbc = self.calc.el.get_pbc() self.kpt_indices = np.array(kpt_indices) for i in range(3): for kp in k: if kp[i]>1E-10 and not pbc[i]: raise AssertionError('Do not set (non-zero) k-points in non-periodic direction!') return nk, k, kl, wk