def band_v(vval, pinfos): '''带内的相互作用''' npat = len(pinfos) ret = numpy.zeros((npat, npat, npat)) ndit = numpy.nditer(ret, flags=['multi_index']) while not ndit.finished: k1idx, k2idx, k3idx = ndit.multi_index #p2这个带 k1v = pinfos[k1idx] k2v = pinfos[k2idx] k3v = pinfos[k3idx] k4v = shift_kv(k1v, k2v) k4v = shift_kv(k4v, Point(-k3v.coord[0], -k3v.coord[1], 1)) #公式中的K ckv = shift_kv(k3v, Point(-k2v.coord[0], -k2v.coord[1], 1)) #p这个带只需要第二个 _, k1nu, _ = get_nu_numpy(k1v.coord[0], k1v.coord[1]) _, k2nu, _ = get_nu_numpy(k2v.coord[0], k2v.coord[1]) _, k3nu, _ = get_nu_numpy(k3v.coord[0], k3v.coord[1]) _, k4nu, _ = get_nu_numpy(k4v.coord[0], k4v.coord[1]) #计算数值 s3_4 = 0.25*numpy.sqrt(3) vab = k1nu[0]*k2nu[1]*k3nu[1]*k4nu[0] + k1nu[1]*k2nu[0]*k3nu[0]*k4nu[1] ret[k1idx, k2idx, k3idx] += 2 * vval * \ numpy.cos(0.25*ckv.coord[0] + s3_4*ckv.coord[1]) * vab vac = k1nu[0]*k2nu[2]*k3nu[2]*k4nu[0] + k1nu[2]*k2nu[0]*k3nu[0]*k4nu[2] ret[k1idx, k2idx, k3idx] += 2 * vval * \ numpy.cos(0.5*ckv.coord[0]) * vac vbc = k1nu[1]*k2nu[2]*k3nu[2]*k4nu[1] + k1nu[2]*k2nu[1]*k3nu[1]*k4nu[2] ret[k1idx, k2idx, k3idx] += 2 * vval * \ numpy.cos(-0.25*ckv.coord[0] + s3_4*ckv.coord[1]) * vbc ndit.iternext() return ret
def load_eqtriangle(lines, hexa, nps, ltris, ladjs): '''读取正三角形''' if nps == -1 or hexa is None: raise ValueError('没有初始化Square') idx_to_tri = {} for line in lines: lstr = line.split(':') idx = int(lstr[1]) v0str = lstr[3].split(',') v1str = lstr[5].split(',') v2str = lstr[7].split(',') v0pt = Point(float(v0str[0]), float(v0str[1]), 1) v1pt = Point(float(v1str[0]), float(v1str[1]), 1) v2pt = Point(float(v2str[0]), float(v2str[1]), 1) rtri = Eqtriangle([v0pt, v1pt, v2pt]) idx_to_tri[idx] = rtri #最上面是2*nps+1,最下面是4*nps-1,一共nps个 num = (2*nps+1) + (4*nps-1) num = num * nps ltris = numpy.ndarray(num, dtype=Eqtriangle) #print(len(idx_to_tri), num) if len(idx_to_tri) != num: raise ValueError('nps和Rtriangle大小不一致') for idx in range(num): ltris[idx] = idx_to_tri[idx] return hexa, nps, ltris, ladjs
def load_triangle(lines, rtg, nps, ltris, ladjs): '''加载三角形\n 加载之后会按照idx的顺序组成一个列表,这样加载adj的时候会按照列表的顺序找到 相应的Triangle ''' if nps == -1 or rtg is None: raise ValueError('没有初始化Square') # if rtg.width >= rtg.height: #如果比较宽 nshape = (nps * numpy.floor_divide(rtg.width, rtg.height), nps) else: nshape = (nps, nps * numpy.floor_divide(rtg.height, rtg.width)) nshape = (numpy.int(nshape[0]), numpy.int(nshape[1])) # ltris = numpy.ndarray(nshape[0] * nshape[1] * 4, dtype=Triangle) if len(lines) != nshape[0] * nshape[1] * 4: raise ValueError('ltris读取时长度对应不上') for line in lines: lstr = line.split(':') idx = int(lstr[1]) v0str = lstr[3].split(',') v1str = lstr[5].split(',') v2str = lstr[7].split(',') v0pt = Point(float(v0str[0]), float(v0str[1]), 1) v1pt = Point(float(v1str[0]), float(v1str[1]), 1) v2pt = Point(float(v2str[0]), float(v2str[1]), 1) tri = Triangle([v0pt, v1pt, v2pt]) ltris[idx] = tri return rtg, nps, ltris, ladjs
def pi_ab_minus_ec(posia, negaa, lamb, qval, dispb, ksft, area): '''使用能量cutoff作为flow parameter的bubble\n posi是dispa为+LAMBDA的边,nega是dispa为-LAMBDA的边, lamb是LAMBDA\n 这两个边应该是限制在dispa这个带的第n个patch中的,这两个边也就暗含了n\n dispa和dispb是两个带的色散关系\n qval是需要平移的大小,应该用一个Point来包装,\n kshf是动量相加的函数, 这个函数应该能处理好到第一布里渊区的映射\n ```(10.112)本身已经处理好了动量守恒,k, k-q是需要满足动量守恒的关系的,而处理好``` ```k-q到第一布里渊区的映射就处理好了Umklapp``` ''' ''' 10.112中的 PI^-(n, q) = -LAMBDA (2pi)^-2 beta^-1 Int_{k in k_n} G'(k)G(- k + Q) = -LAMBDA (2pi)^-2 Int_{k in k_n} CITA() -DELTA() { beta^-1 sum_{omega} [(i*omega-disp(k))(-i*omega-disp(-k + q))]^-1 } 在零温下这个频率积分等于,注意-k那里把频率也给反过来了 +CITA(+disp(k)disp(-k+q)) / (abs(disp(k)) + abs(disp(-k+q))) 原式就等于 = LAMBDA (2pi)^-2 Int_{k in k_n} { DELTA(abs(disp(k))-LAMBDA) CITA(abs(disp(-k+q)-LAMBDA)) CITA(disp(k)disp(-k+q)) / (abs(disp(k)) + abs(disp(-k+q))) } 第二个CITA限制了disp(k)和disp(-k+q)同号,积分积掉DELTA,分类讨论正负 = LAMBDA (2pi)^-2 { Int_{disp(k) = +LAMBDA} CITA(disp(-k+q) - LAMBDA) / (LAMBDA + disp(-k+q)) + Int_{disp(k) = -LAMBDA} CITA(-disp(-k+q) -LAMBDA) / (LAMBDA - disp(-k+q)) } ''' #积分正LAMBDA的线 intposi = 0. for edg in posia: kval = middle_point(edg.ends[0], edg.ends[1]) nega_k = Point(-kval.coord[0], -kval.coord[1], 1) kprim = ksft(nega_k, qval) #CITA disp_kprim = dispb(kprim.coord[0], kprim.coord[1]) if disp_kprim < lamb: continue #要计算线元的长度 intposi += edg.length / (lamb + disp_kprim) #积分负LAMBDA的线 intnega = 0. for edg in negaa: kval = middle_point(edg.ends[0], edg.ends[1]) nega_k = Point(-kval.coord[0], -kval.coord[1], 1) kprim = ksft(nega_k, qval) #CITA disp_kprim = dispb(kprim.coord[0], kprim.coord[1]) if -disp_kprim < lamb: continue intnega += edg.length / (lamb - disp_kprim) #乘上系数 result = lamb * (intposi + intnega) / area#numpy.square(numpy.pi*2) return result
def __init__(self, brlu, ltris, ladjs, mpinfo, mlpats, \ mdisp, mdispgd, ksft, lamb0, find_mode): self._brlu = brlu self._ltris = ltris self._nps = numpy.sqrt(len(ltris)) / 2 self._bandnum = len(mpinfo) self._ladjs = ladjs self._mpinfo = mpinfo self._mlpats = mlpats self._mdisp = mdisp self._mdispgd = mdispgd self._ksft = ksft self._lamb0 = lamb0 self._patchnum = len(self._mpinfo[0]) #找到每个对应的n4 #现在每个带都有自己的idx4 if find_mode == 1: data_list = [] idxit = numpy.nditer(U, flags=['multi_index']) step = numpy.minimum(brlu.width, brlu.height) / 10 / self._nps while not idxit.finished: bd1, bd2, bd3, bd4, idx1, idx2, idx3 = idxit.multi_index kv1, kv2, kv3 = mpinfo[bd1, idx1], mpinfo[bd2, idx2], mpinfo[bd3, idx3] kv4 = ksft(ksft(kv1, kv2), Point(-kv3.coord[0], -kv3.coord[1], 1)) data_list.append( (kv4, mpinfo[bd4, :], mdisp[bd4], mdispgd[bd4], step)) #idx4 = find_patch(kv4, mpinfo[bd4, :], mdisp[bd4],\ # mdispgd[bd4], numpy.pi / 2 / self._nps) #self._mk4tab[idxit.multi_index] = idx4 idxit.iternext() with multiprocessing.Pool(get_procs_num()) as pool: self._mk4tab = pool.starmap(find_patch, data_list) self._mk4tab = numpy.reshape(self._mk4tab, U.shape) return data_list = [] idxit = numpy.nditer(U, flags=['multi_index']) while not idxit.finished: bd1, bd2, bd3, bd4, idx1, idx2, idx3 = idxit.multi_index kv1, kv2, kv3 = mpinfo[bd1, idx1], mpinfo[bd2, idx2], mpinfo[bd3, idx3] kv4 = ksft(ksft(kv1, kv2), Point(-kv3.coord[0], -kv3.coord[1], 1)) data_list.append((kv4, mpinfo[bd4, :])) idxit.iternext() find_func = {2: find_patch_mode2, 3: find_patch_mode3}[find_mode] with multiprocessing.Pool(get_procs_num()) as pool: self._mk4tab = pool.starmap(find_func, data_list) self._mk4tab = numpy.reshape(self._mk4tab, U.shape)
def get_sublattice_u(umat, pinfos): '''将能带表示变回到子格子表示''' npat = len(pinfos) ret = numpy.zeros((3, 3, 3, 3, npat, npat, npat)) place_holder = numpy.zeros((npat, npat, npat)) ndit = numpy.nditer(place_holder, flags=['multi_index']) while not ndit.finished: k1idx, k2idx, k3idx = ndit.multi_index #p2这个带 k1v = pinfos[k1idx] k2v = pinfos[k2idx] k3v = pinfos[k3idx] k4v = shift_kv(k1v, k2v) k4v = shift_kv(k4v, Point(-k3v.coord[0], -k3v.coord[1], 1)) _, k1nu, _ = get_nu_numpy(k1v.coord[0], k1v.coord[1]) _, k2nu, _ = get_nu_numpy(k2v.coord[0], k2v.coord[1]) _, k3nu, _ = get_nu_numpy(k3v.coord[0], k3v.coord[1]) _, k4nu, _ = get_nu_numpy(k4v.coord[0], k4v.coord[1]) place_holder2 = numpy.zeros((3, 3, 3, 3)) ndit2 = numpy.nditer(place_holder2, flags=['multi_index']) while not ndit2.finished: si1, si2, si3, si4 = ndit2.multi_index ret[si1, si2, si3, si4, k1idx, k2idx, k3idx] =\ umat[k1idx, k2idx, k3idx] * k1nu[si1] * k2nu[si2] * k3nu[si3] * k4nu[si4] ndit2.iternext() ndit.iternext() return ret
def get_patches(brlu: Square, npatch, dispfun): '''获得费米面上面的patch\n dispfun是色散关系\n ''' gap = numpy.pi * 2 / npatch angles = [gap * (idx + 0.5) for idx in range(npatch)] #解出每个角度下和费米面的交点 patches = [] #半径最大是这么多 maxv = brlu.width * 1.414 / 2. for ang in angles: xcoff = numpy.cos(ang) ycoff = numpy.sin(ang) def __raddisp(rad): kxv = rad * xcoff if numpy.abs(kxv) > numpy.pi: kxv = numpy.sign(kxv) * numpy.pi kyv = rad * ycoff if numpy.abs(kyv) > numpy.pi: kyv = numpy.sign(kyv) * numpy.pi return dispfun(kxv, kyv) rrad = optimize.bisect(__raddisp, 0., maxv) patches.append(Point(rrad * xcoff, rrad * ycoff, 1)) return patches
def pi_plus_ec(posi, nega, lamb, qval, disp, ksft, area): '''使用能量cutoff作为flow parameter的bubble\n posi是能量为+LAMBDA的边,nega是能量为-LAMBDA的边, lamb是LAMBDA\n disp是色散关系,qval是需要平移的大小,应该用一个Point来包装,\n kshf是动量相加的函数, 这个函数应该能处理好到第一布里渊区的映射\n area是第一布里渊区的面积\n ```(10.112)本身已经处理好了动量守恒,k, k-q是需要满足动量守恒的关系的,而处理好``` ```k-q到第一布里渊区的映射就处理好了Umklapp``` ''' ''' 10.112中的 PI^+(n, q) = +LAMBDA (2pi)^-2 beta^-1 Int_{k in k_n} G'(k)G(k - Q) 其中有一个beta是频率积分带来的,2pi^2是动量积分带来的 G(k)=CITA(LAMBDA < abs(disp(k))) / i*omega - disp(k) G'(k)=-DELTA(abs(disp(k))-LAMBDA) / i*omege - disp(k) 在零温的情况下10.112中的频率部分可以积分出来,此后的k都是不包含频率的 = +LAMBDA (2pi)^-2 Int_{k in k_n} CITA() -DELTA() { beta^-1 sum_{omega} [(i*omega-disp(k))(i*omega-disp(k - q))]^-1 } 花括号中的内容求和完之后等于 - CITA(-disp(k)disp(k-q)) / (abs(disp(k)) + abs(disp(k-p))) 积分会变成 = +LAMBDA (2pi)^-2 Int_{k in k_n} DELTA(abs(disp(k))-LAMBDA) CITA(LAMBDA<abs(disp(k-q))) CITA(-disp(k)disp(k-q)) / (abs(disp(k)) + abs(disp(k-p))) 因为采用的能量cutoff中有一个 DELTA(abs(disp(k))-LAMBDA),disp(k)等于正的或者负的LAMBDA 而CITA(-disp(k)disp(k-q))限制了disp(k)和disp(k-q)符号相反 所以上式变成 (第一项disp(k)=LAMBDA>0,于是disp(k-q)<0,而且abs(disp(k))=-disp(k)>LAMBDA) (第二项类似,分子中的abs(disp(k))都可以直接换成LAMBDA,abs(disp(k-q))也都知道符号) = +LAMBDA (2pi)^-2 Int_{k in kn} { DELTA(disp(k)-LAMBDA)CITA(-disp(k-q)-LAMBDA) / (LAMBDA - disp(k - q)) DELTA(disp(k)+LAMBDA)CITA(disp(k-q)-LAMBDA) / (LAMBDA + disp(k - q)) } 还可以从积分里面把DELTA给积分掉,这样对于二维平面的积分也会变成对 disp(k) = LAMBDA 或者 -LAMBDA的线的积分 = +LAMBDA (2pi)^-2 * [Int_{disp(k) = +LAMBDA} CITA(-disp(k-q)-LAMBDA) / (LAMBDA - disp(k - q))] +[Int_{disp(k) = -LAMBDA} CITA(disp(k-q)-LAMBDA) / (LAMBDA + disp(k - q)) ] ''' nega_q = Point(-qval.coord[0], -qval.coord[1], 1) #积分正LAMBDA的线 intposi = 0. for edg in posi: kval = middle_point(edg.ends[0], edg.ends[1]) kprim = ksft(kval, nega_q) #CITA disp_kprim = disp(kprim.coord[0], kprim.coord[1]) if -disp_kprim < lamb: continue #线积分,计算线元的长度 intposi += edg.length / (lamb - disp_kprim) #积分负LAMBDA的线 intnega = 0. for edg in nega: kval = middle_point(edg.ends[0], edg.ends[1]) kprim = ksft(kval, nega_q) #CITA disp_kprim = disp(kprim.coord[0], kprim.coord[1]) if disp_kprim < lamb: continue intnega += edg.length / (lamb + disp_kprim) #乘上系数 result = lamb * (intposi + intnega) / area #numpy.square(numpy.pi*2) return result
def get_von_hove_patches(npat): '''获取平分von Hove的patches''' #pylint: disable=cell-var-from-loop #一共有6个M点 mpts = [ Point(3.1415926, 3.1415926 / 1.7320508, 1), Point(0, 2*3.1415926 / 1.7320508, 1), Point(-3.1415926, 3.1415926 / 1.7320508, 1), Point(-3.1415926, -3.1415926 / 1.7320508, 1), Point(0, -2*3.1415926 / 1.7320508, 1), Point(3.1415926, -3.1415926 / 1.7320508, 1) ] angs = [] pat_per_k = npat // 6 gap = 1 / pat_per_k for idx in range(6): ridx = idx + 1 if idx + 1 < 6 else 0 for pidx in range(pat_per_k): omega = (pidx + 0.5) * gap vpt = middle_point(mpts[idx], mpts[ridx], sc1=1-omega, sc2=omega) angs.append(get_absolute_angle(vpt.coord[0], vpt.coord[1])) pats = [] for ang in angs: rrad = optimize.bisect( lambda rad: dispersion(rad*numpy.cos(ang), rad*numpy.sin(ang)), 0, 2*numpy.pi/numpy.sqrt(3) ) pats.append(Point(rrad*numpy.cos(ang), rrad*numpy.sin(ang), 1)) return pats
def shift_kv(kpt: Point, sft: Point) -> Point: '''将一个k点平移,然后重新对应到第一布里渊区''' dest = [kpt.coord[idx] + sft.coord[idx] for idx in range(2)] while numpy.abs(dest[0]) > numpy.pi: #如果大于第一布里渊区就向零靠拢2pi dest[0] -= numpy.sign(dest[0]) * numpy.pi * 2 while numpy.abs(dest[1]) > numpy.pi: dest[1] -= numpy.sign(dest[1]) * numpy.pi * 2 return Point(dest[0], dest[1], 1)
def get_rect_patches(npatch, dispstr): '''获取长方形的patches''' from .patches import get_patches from .square import dispersion as squdisp from .square import hole_disp as squhole_disp from .square import brillouin as sbr disp = squdisp if dispstr == 'square' else squhole_disp spats = get_patches(sbr(), npatch, disp) patches = [Point(pat.coord[0] / 2., pat.coord[1], 1) for pat in spats] return patches
def intra_band_u(uval, mpinfos): '''带内的相互作用''' size = numpy.shape(mpinfos) ret = numpy.zeros((2, 2, 2, 2, size[1], size[1], size[1])) place_holder = numpy.zeros((size[1], size[1], size[1])) ndit = numpy.nditer(place_holder, flags=['multi_index']) while not ndit.finished: k1idx, k2idx, k3idx = ndit.multi_index #d1这个带 k1v = mpinfos[0, k1idx] k2v = mpinfos[0, k2idx] k3v = mpinfos[0, k3idx] k4v = shift_kv(k1v, k2v) k4v = shift_kv(k4v, Point(-k3v.coord[0], -k3v.coord[1], 1)) #print(k1v, k2v, k3v, k4v) #d这个带只需要第三个 _, _, k1nu = get_nu_numpy(k1v.coord[0], k1v.coord[1]) _, _, k2nu = get_nu_numpy(k2v.coord[0], k2v.coord[1]) _, _, k3nu = get_nu_numpy(k3v.coord[0], k3v.coord[1]) _, _, k4nu = get_nu_numpy(k4v.coord[0], k4v.coord[1]) #计算数值 for idx in range(3): ret[0, 0, 0, 0, k1idx, k2idx, k3idx] +=\ uval * k1nu[idx] * k2nu[idx] * k3nu[idx] * k4nu[idx] #p2这个带 k1v = mpinfos[1, k1idx] k2v = mpinfos[1, k2idx] k3v = mpinfos[1, k3idx] k4v = shift_kv(k1v, k2v) k4v = shift_kv(k4v, Point(-k3v.coord[0], -k3v.coord[1], 1)) #p这个带只需要第二个 _, k1nu, _ = get_nu_numpy(k1v.coord[0], k1v.coord[1]) _, k2nu, _ = get_nu_numpy(k2v.coord[0], k2v.coord[1]) _, k3nu, _ = get_nu_numpy(k3v.coord[0], k3v.coord[1]) _, k4nu, _ = get_nu_numpy(k4v.coord[0], k4v.coord[1]) #计算数值 for idx in range(3): ret[1, 1, 1, 1, k1idx, k2idx, k3idx] +=\ uval * k1nu[idx] * k2nu[idx] * k3nu[idx] * k4nu[idx] ndit.iternext() return ret
def square_split(squ: Square, nps): '''先将一个正方形切分成很多个小正方形\n 然后把小正方形切分成三角 ''' lsqus = numpy.ndarray((nps, nps), dtype=Square) width = squ.width / nps statx, staty = squ.vertex[1].coord #从左下角开始,先水平的顺序进行标号 # [idx2] # nps # ... # 1 x x # 0 x x # 0 1 ... nps [idx1] for idx1 in range(nps): for idx2 in range(nps): xct = (idx1 + 0.5) * width + statx yct = (idx2 + 0.5) * width + staty lsqus[idx1, idx2] = Square(Point(xct, yct, 1), width) #将每个小正方切分 ltris = numpy.ndarray((nps, nps, 4), dtype=Rtriangle) for idx1 in range(nps): for idx2 in range(nps): ltris[idx1, idx2, :] = single_square_split(lsqus[idx1, idx2]) #找到每个小三角形挨着的小三角形 #这个时候的顺序应该是和小三角形的边的顺序一致的 ladjs = numpy.ndarray((nps, nps, 4), dtype=numpy.object) for idx1 in range(nps): for idx2 in range(nps): #上面的那个小三角,第一条边是右侧,第二条是上边 adjs = [ltris[idx1, idx2, 3], None, ltris[idx1, idx2, 1]] if idx2 + 1 < nps: adjs[1] = ltris[idx1, idx2 + 1, 2] ladjs[idx1, idx2, 0] = adjs #左面的小三角,第一条边是上边,第二条是左面 adjs = [ltris[idx1, idx2, 0], None, ltris[idx1, idx2, 2]] if idx1 - 1 >= 0: adjs[1] = ltris[idx1 -1, idx2, 3] ladjs[idx1, idx2, 1] = adjs #下面的小三角,第一条边是左面,第二条是下面 adjs = [ltris[idx1, idx2, 1], None, ltris[idx1, idx2, 3]] if idx2 - 1 >= 0: adjs[1] = ltris[idx1, idx2 - 1, 0] ladjs[idx1, idx2, 2] = adjs #右面的小三角,第一条边是下面,第二条是右边 adjs = [ltris[idx1, idx2, 2], None, ltris[idx1, idx2, 0]] if idx1 + 1 < nps: adjs[1] = ltris[idx1 + 1, idx2, 1] ladjs[idx1, idx2, 3] = adjs #将小三角和它对应的近邻都reshape ltris = numpy.reshape(ltris, nps*nps*4) ladjs = numpy.reshape(ladjs, nps*nps*4) return ltris, ladjs
def get_exchange_gamma(jval, pinfos): '''获取交换相互作用的有效大小''' pnum = len(pinfos) result = numpy.zeros((pnum, pnum, pnum)) nditer = numpy.nditer(result, flags=['multi_index']) co1 = 0.5 co2 = numpy.sqrt(3) * 0.5 while not nditer.finished: kidx1, kidx2, kidx3 = nditer.multi_index kv1, kv2, kv3 = pinfos[kidx1], pinfos[kidx2], pinfos[kidx3] #q1v = k_2 - k_4 = k_3 - k_1 q1v = shift_kv(kv3, Point(-kv1.coord[0], -kv1.coord[1], 1)) #q2v = k_1 - k_4 = k_3 - k_2 q2v = shift_kv(kv3, Point(-kv2.coord[0], -kv2.coord[1], 1)) phase = numpy.cos(-co1*q1v.coord[0] + co2*q1v.coord[1]) phase += numpy.cos(co1*q1v.coord[0] + co2*q1v.coord[1]) phase += numpy.cos(q1v.coord[0]) phase += 0.5*numpy.cos(-co1*q2v.coord[0] + co2*q2v.coord[1]) phase += 0.5*numpy.cos(co1*q2v.coord[0] + co2*q2v.coord[1]) phase += 0.5*numpy.cos(q2v.coord[0]) result[kidx1, kidx2, kidx3] = -jval * phase nditer.iternext() return result
def get_patches(npat): '''获得三角格子的patches,最简单的版本,按角度切分''' #pylint: disable=cell-var-from-loop deltaa = 2*numpy.pi / npat angs = [(idx+0.5) * deltaa for idx in range(npat)] #print(angs) pats = [] for ang in angs: rrad = optimize.bisect( lambda rad: dispersion(rad*numpy.cos(ang), rad*numpy.sin(ang)), 0, 2*numpy.pi/numpy.sqrt(3) ) pats.append(Point(rrad*numpy.cos(ang), rrad*numpy.sin(ang), 1)) return pats
def get_s_band_patches(pnum): '''获得s能带的patch''' if (pnum % 4) != 0: raise ValueError('pnum必须是4的倍数') ppnum = pnum // 4 patches = [] #先算右边 gap = numpy.pi / 2 / ppnum maxr = numpy.pi * 1.414 for idx in range(ppnum * 2): angle = (idx + 0.5) * gap ycoff = numpy.cos(angle) xcoff = numpy.sin(angle) def __raddisp(rad): '''以半径为基准的色散''' xcord = numpy.pi - rad * xcoff ycord = ycoff * rad return s_band_disp(xcord, ycord) rrad = optimize.bisect(__raddisp, 0., maxr) patches.append(Point(numpy.pi - rrad * xcoff, ycoff * rrad, 1)) #再算左边 for idx in range(ppnum * 2): angle = (idx + 0.5) * gap ycoff = -numpy.cos(angle) xcoff = numpy.sin(angle) def __raddisp(rad): '''以半径为基准的色散''' xcord = -numpy.pi + rad * xcoff ycord = ycoff * rad return s_band_disp(xcord, ycord) rrad = optimize.bisect(__raddisp, 0., maxr) patches.append(Point(-numpy.pi + rrad * xcoff, ycoff * rrad, 1)) return patches
def pi_ab_minus_tf(ltris, tarea, lamb, dispa, dispb, qval, ksft, area): '''温度流的- 这里的lamb就是T,ltris中的所有三角都应该要在同一个patch中, tarea是每个小三角形的面积,dispa是和k相关的那个能带,dispb是-k+q相关的 ''' result = 0. for tri in ltris: #这个小三角形的k值 kval = tri.center nega_k = Point(-kval.coord[0], -kval.coord[1], 1) #-k+q kprim = ksft(nega_k, qval) #epsilon_k eps_k = dispa(kval.coord[0], kval.coord[1]) #-epsilon_{-k+q} neps_kp = -dispb(kprim.coord[0], kprim.coord[1]) #这个时候,因为epsilon_{-k+q}前面已经有了负号,分母上还是负号 if numpy.abs(eps_k - neps_kp) < 1.e-10: #如果两个数值比较接近, Pi^{-}和Pi^{+}的公式完全一样,就是第二个能量要加个负号 # lim (eps_k -> -eps_kp) Pi^{-} = # 1/T (e^{eps/T} (-eps/T*e^{eps/T} + eps/T + e^{eps/T} + 1)) / (e^{eps/T} + 1)^3 bval = eps_k / lamb if bval > 25: warnings.warn("数值不稳定", RuntimeWarning) return 0. expb = numpy.exp(bval) num = expb * (-bval * expb + bval + expb + 1) den = numpy.power((1+expb), 3) d_val = num / den / lamb else: if (eps_k / lamb) > 25: warnings.warn("数值不稳定", RuntimeWarning) num_left = 0. else: #e^{epsilon_k / T} exp_k_t = numpy.exp(eps_k / lamb) num_left = eps_k / lamb * exp_k_t / numpy.square(1 + exp_k_t) if (neps_kp / lamb) > 25: warnings.warn("数值不稳定", RuntimeWarning) num_righ = 0. else: #e^{-epsilon_{-k+q} / T} exp_nkp_t = numpy.exp(neps_kp / lamb) num_righ = neps_kp / lamb * exp_nkp_t\ / numpy.square(1 + exp_nkp_t) d_val = (num_left - num_righ) / (eps_k - neps_kp) result += d_val * tarea result = result / area return result
def pi_ab_plus_tf(ltris, tarea, lamb, dispa, dispb, qval, ksft, area): '''温度流的+ 这里的lamb就是T,ltris中的所有三角都应该要在同一个patch中, tarea是每个小三角形的面积,dispa是和k相关的那个能带,dispb是k-q相关的 ''' nega_q = Point(-qval.coord[0], -qval.coord[1], 1) result = 0. for tri in ltris: #这个小三角形的k值 kval = tri.center #k-q kprim = ksft(kval, nega_q) #epsilon_k eps_k = dispa(kval.coord[0], kval.coord[1]) #epsilon_{k-q} eps_kp = dispb(kprim.coord[0], kprim.coord[1]) if numpy.abs(eps_k - eps_kp) < 1.e-10: #如果特别小,可以利用 # lim (eps_k -> eps_kp) Pi^{+} = # 1/T (e^{eps/T} (-eps/T*e^{eps/T} + eps/T + e^{eps/T} + 1)) / (e^{eps/T} + 1)^3 bval = eps_kp / lamb #如果本身就很大,分母会比较大导致接近0 if bval > 25: warnings.warn("数值不稳定", RuntimeWarning) return 0. expb = numpy.exp(bval) num = expb * (-bval * expb + bval + expb + 1) den = numpy.power((1+expb), 3) d_val = num / den / lamb else: if (eps_k / lamb) > 25: warnings.warn("数值不稳定", RuntimeWarning) num_left = 0. else: #exp^{epsilon_k / T} exp_k_t = numpy.exp(eps_k / lamb) num_left = eps_k / lamb * exp_k_t / numpy.square(1 + exp_k_t) if (eps_kp / lamb) > 25: warnings.warn("数值不稳定", RuntimeWarning) num_righ = 0. else: #e^{epsilon_{k-q} / T} exp_kp_t = numpy.exp(eps_kp / lamb) num_righ = eps_kp / lamb * exp_kp_t\ / numpy.square(1 + exp_kp_t) d_val = (num_left - num_righ) / (eps_k - eps_kp) result += d_val * tarea result = result / area return result
def load_hexagon(lines, hexa, nps, ltris, ladjs): '''读取六边形的段落''' cntcor = None height = None nps = None for line in lines: if line.startswith('center: '): corstr = line[8:].split(',') cntcor = (float(corstr[0]), float(corstr[1])) if line.startswith('height: '): height = float(line[8:]) if line.startswith('nps: '): nps = int(line[4:]) hexa = Hexagon(Point(cntcor[0], cntcor[1], 1), height) return hexa, nps, ltris, ladjs
def load_rtriangle(lines, squ, nps, ltris, ladjs): '''解析处理三角切分的段落\n 这个处理完之后会是一个按照idx进行排序的list ''' if nps == -1 or squ is None: raise ValueError('没有初始化Square') idx_to_tri = {} for line in lines: lstr = line.split(':') idx = int(lstr[1]) rtvstr = lstr[3].split(',') v1str = lstr[5].split(',') v2str = lstr[7].split(',') rvpt = Point(float(rtvstr[0]), float(rtvstr[1]), 1) v1pt = Point(float(v1str[0]), float(v1str[1]), 1) v2pt = Point(float(v2str[0]), float(v2str[1]), 1) rtri = Rtriangle(rvpt, v1pt, v2pt) idx_to_tri[idx] = rtri ltris = numpy.ndarray(nps*nps*4, dtype=Rtriangle) if len(idx_to_tri) != nps*nps*4: raise ValueError('nps和Rtriangle大小不一致') for idx in range(nps*nps*4): ltris[idx] = idx_to_tri[idx] return squ, nps, ltris, ladjs
def load_square(lines, squ, nps, ltris, ladjs): '''解析处理正方形的段落''' cntcor = None width = None nps = None for line in lines: if line.startswith('center: '): corstr = line[8:].split(',') cntcor = (float(corstr[0]), float(corstr[1])) if line.startswith('width: '): width = float(line[7:]) if line.startswith('nps: '): nps = int(line[4:]) squ = Square(Point(cntcor[0], cntcor[1], 1), width) return squ, nps, ltris, ladjs
def load_rectangle(lines, rtg, nps, ltris, ladjs): '''加载长方形''' cntcor = None width = None height = None nps = None for line in lines: if line.startswith('center: '): corstr = line[8:].split(',') cntcor = (float(corstr[0]), float(corstr[1])) if line.startswith('width: '): width = float(line[7:]) if line.startswith('height: '): height = float(line[8:]) if line.startswith('nps: '): nps = int(line[4:]) rtg = Rectangle(Point(cntcor[0], cntcor[1], 1), width, height) return rtg, nps, ltris, ladjs
def get_initu(spats, ppats, uval): '''获取初始化的u值''' pnum = len(spats) if pnum != len(ppats): raise ValueError('patch数量不一致') place_holder = numpy.ndarray((2, 2, 2, 2, pnum, pnum, pnum)) #kv4直接通过前三个kv可以确定,而他属于的idx4这里是不需要的 phiter = numpy.nditer(place_holder, flags=['multi_index']) while not phiter.finished: bd1, bd2, bd3, bd4, idx1, idx2, idx3 = phiter.multi_index kv1 = spats[idx1] if bd1 == 0 else ppats[idx1] kv2 = spats[idx2] if bd2 == 0 else ppats[idx2] kv3 = spats[idx3] if bd3 == 0 else ppats[idx3] kv4 = shift_kv(shift_kv(kv1, kv2), Point(-kv3.coord[0], -kv3.coord[1], 1)) place_holder[bd1, bd2, bd3, bd4, idx1, idx2, idx3] =\ band_uval(uval, bd1, bd2, bd3, bd4, kv1, kv2, kv3, kv4) phiter.iternext() return place_holder
def shift_kv(kpt: Point, sft: Point): '''将一个动量平移''' dest = [kpt.coord[idx] + sft.coord[idx] for idx in range(2)] #找到离目标最近的一个第一布里渊区的中心 #如果这个点距离中心是最近的,那么他就在第一布里渊区里面了,如果 #离其他的点近,就平移一次,再检查一遍 b1x = -6.283185307179586#-2*numpy.pi b1y = 3.6275987284684357#2*numpy.pi/numpy.sqrt(3) brlu_cents = [(0, 0), (b1x, b1y), (0, 2*b1y), (-b1x, b1y),\ (-b1x, -b1y), (0, -2*b1y), (b1x, -b1y)] #计算距离 dis2cents = [numpy.square(dest[0]-cnt[0]) + numpy.square(dest[1]-cnt[1])\ for cnt in brlu_cents] while numpy.argmin(dis2cents) != 0: ncnt = numpy.argmin(dis2cents) dest[0] = dest[0] - brlu_cents[ncnt][0] dest[1] = dest[1] - brlu_cents[ncnt][1] dis2cents = [numpy.square(dest[0]-cnt[0]) + numpy.square(dest[1]-cnt[1])\ for cnt in brlu_cents] return Point(dest[0], dest[1], 1)
def precompute_qfs(lval): '''计算q_fs实际上也不需要多余的变量 bd2, bd3, idx2, idx3 ''' global QUICKQFS #fs的所有自由度 data_list = [] place_holder = numpy.ndarray(( #alpha, beta, bd2, bd3 CONFIG.bandnum, CONFIG.bandnum, CONFIG.bandnum, CONFIG.bandnum, #nidx(alpha), idx2(bd2), idx3(bd3) CONFIG.patchnum, CONFIG.patchnum, CONFIG.patchnum)) nditer = numpy.nditer(place_holder, flags=['multi_index']) # area = CONFIG.brlu.width * CONFIG.brlu.height ltris = CONFIG.ltris tarea = area / len(ltris) mpinfo = CONFIG.mpinfo ksft = CONFIG.ksft lamb = CONFIG.lamb0 * numpy.exp(-lval) mdisp = CONFIG.mdisp # while not nditer.finished: alpha, beta, bd2, bd3, nidx, idx2, idx3 = nditer.multi_index kv2, kv3 = mpinfo[bd2, idx2], mpinfo[bd3, idx3] q_fs = ksft(kv3, Point(-kv2.coord[0], -kv2.coord[1], 1)) data_list.append( (PATTRIS[alpha, nidx], tarea, lamb,\ mdisp[alpha], mdisp[beta], q_fs, ksft, area) ) nditer.iternext() # with multiprocessing.Pool(get_procs_num()) as pool: result = pool.starmap(pi_ab_plus_tf, data_list) QUICKQFS = (lval, numpy.reshape(result, place_holder.shape))
def inverse_uval(pinfos, spats, ppats, uval): '''将band表示转换回basis表示,需要一系列的patches, 然后利用find_patch找到这些patches对应的值''' from .patches import find_patch pnum = len(pinfos) place_holder = numpy.zeros((2, 2, 2, 2, pnum, pnum, pnum)) img_part = numpy.zeros_like(place_holder) phiter = numpy.nditer(place_holder, flags=['multi_index']) step = numpy.pi / 100 #找出这些patches对应的P_b(k) allpatdic = numpy.ndarray((2, pnum), dtype=int) #print(pinfos[0]) #print(find_patch(pinfos[0], spats, s_band_disp, s_band_gd, step)) #print(find_patch(pinfos[0], ppats, p_band_disp, p_band_gd, step)) #raise for idx, pat in enumerate(pinfos, 0): allpatdic[0, idx] = find_patch(pat, spats, s_band_disp, s_band_gd, step) allpatdic[1, idx] = find_patch(pat, ppats, p_band_disp, p_band_gd, step) while not phiter.finished: st1, st2, st3, st4, idx1, idx2, idx3 = phiter.multi_index kv1 = pinfos[idx1] kv2 = pinfos[idx2] kv3 = pinfos[idx3] kv4 = shift_kv(shift_kv(kv1, kv2), Point(-kv3.coord[0], -kv3.coord[1], 1)) #每个点在不同能带下对应的patch patdic = numpy.ndarray((2, 3), dtype=int) patdic[:, 0] = allpatdic[:, idx1] patdic[:, 1] = allpatdic[:, idx2] patdic[:, 2] = allpatdic[:, idx3] #bval = basis_uval(uval, st1, st2, st3, st4, kv1, kv2, kv3, kv4, patdic) bval = basis_uval_2(uval, st1, st2, st3, st4, patdic, spats, ppats) place_holder[st1, st2, st3, st4, idx1, idx2, idx3] = numpy.real(bval) img_part[st1, st2, st3, st4, idx1, idx2, idx3] = numpy.imag(bval) phiter.iternext() return place_holder, img_part
def band_u(uval, pinfos): '''带内的相互作用''' npat = len(pinfos) ret = numpy.zeros((npat, npat, npat)) ndit = numpy.nditer(ret, flags=['multi_index']) while not ndit.finished: k1idx, k2idx, k3idx = ndit.multi_index #p2这个带 k1v = pinfos[k1idx] k2v = pinfos[k2idx] k3v = pinfos[k3idx] k4v = shift_kv(k1v, k2v) k4v = shift_kv(k4v, Point(-k3v.coord[0], -k3v.coord[1], 1)) #p这个带只需要第二个 _, k1nu, _ = get_nu_numpy(k1v.coord[0], k1v.coord[1]) _, k2nu, _ = get_nu_numpy(k2v.coord[0], k2v.coord[1]) _, k3nu, _ = get_nu_numpy(k3v.coord[0], k3v.coord[1]) _, k4nu, _ = get_nu_numpy(k4v.coord[0], k4v.coord[1]) #计算数值 for idx in range(3): ret[k1idx, k2idx, k3idx] +=\ uval * k1nu[idx] * k2nu[idx] * k3nu[idx] * k4nu[idx] ndit.iternext() return ret
def brillouin(): '''布里渊区''' return Hexagon(Point(0, 0, 1), 2*numpy.pi/numpy.sqrt(3))
def main(): """ Main Function """ print("CG LAB 3") print("Brihat Ratna Bajracharya\n19/075\n") global INPUT_FILE try: input_file_arg = sys.argv[1] if os.path.exists(input_file_arg): INPUT_FILE = input_file_arg print("Using file: " + INPUT_FILE + "\n") else: print("Input file not found") INPUT_FILE = 'cg_lab_3_input_file_5' print("Using file: " + INPUT_FILE + "\n") except: print("No input file given. Taking default") print("Using file: " + INPUT_FILE + "\n") try: ''' reads input file ''' in_file = open(INPUT_FILE, 'r') ''' get number of vertices for polygon ''' print("Enter number of vertex of polygon:"), vertex_num = int(in_file.readline()) print(vertex_num) ''' reads coords of point ''' input_coords = in_file.readline() input_coords_list = input_coords.split() # print(input_coords_list) ''' initialize vertex list ''' points = [None] * vertex_num ''' get coordinates of each vertices ''' for index in range(vertex_num): print(" Enter coordinates of vertex V{}:".format(index + 1)), input_coords_point = input_coords_list[index].split(',') points[index] = Point(int(input_coords_point[0]), int(input_coords_point[1])) print(points[index]) ''' calculate centroid of polygon ''' centroid = Point( sum([point.x for point in points]) / len(points), sum([point.y for point in points]) / len(points)) # print("Centroid of all Points: " + str(centroid)) ''' sort vertices of polygon in anti-clockwise order ''' sorted_p = copy.deepcopy(points) sorted_p.sort( key=lambda p: math.atan2(p.y - centroid.y, p.x - centroid.x)) ''' show points in sorted order ''' # print("\nPoints in sorted order") # for index in range(vertex_num): # print(sorted_p[index]), # print("\n") polygon = CircularDoublyLinkedList() for index in range(vertex_num): polygon.append(sorted_p[index]) ''' displays content of polygon and count of vertices ''' polygon.display("Vertices of Polygon (sorted)") # polygon.show_count() ''' polygon convex test ''' convex_check = is_polygon_convex(polygon) print("\nRESULT: Polygon is {}convex.".format( '' if convex_check else 'not ')) if convex_check: ''' check point inclusion only if polygon is convex ''' print("\n\nPOINT INCLUSION BY TURN TEST") print("\n Enter coordinates of Query Point (P):"), ''' read query point from file ''' qp = in_file.readline().split()[0].split(',') # print(qp) query_point = Point(int(qp[0]), int(qp[1])) print(query_point) ''' point inclusion using turn test ''' is_point_in_polygon = is_point_inclusion(polygon, query_point) print("\nRESULT: Query Point {}inside given polygon.".format( '' if is_point_in_polygon else 'not ')) print("\n\nRAY CASTING") print("\n Enter coordinates of ray point (R):"), ''' read ray point start from file ''' if not convex_check: in_file.readline() rp = in_file.readline().split()[0].split(',') # print(rp) ray_point = Point(int(rp[0]), int(rp[1])) print(ray_point) ray_on_edge = check_ray_on_polygon_boundary(polygon, ray_point) if ray_on_edge: print("\nRESULT: Ray origin on boundary of polygon.") print( "\tRay origin on edge joining points {}.".format(ray_on_edge)) else: ''' assuming ray infinity point to the right side of polygon ''' ray_xcoord_infinity = max([point.x for point in sorted_p]) # ray_ycoord_infinity = sum([point.y for point in sorted_p]) / vertex_num ray_point_infinity = Point(ray_xcoord_infinity + 1, ray_point.y) ray_line_infinity = LineSegment(ray_point, ray_point_infinity) # print("\n Ray Point Infinity: " + str(ray_point_infinity)) # print(" Ray Line: " + str(ray_line_infinity)) ''' ray intersection using line_segment_intersection test ''' ray_intersection_count = ray_casting(polygon, ray_line_infinity) ray_casting_result = ray_intersection_count % 2 print("\nRESULT: Ray origin {} of polygon.".format( 'inside' if ray_casting_result else 'outside')) in_file.close() print("\nDONE.") except Exception as e: print("\n\nERROR OCCURED !!!\n Type of Error: " + type(e).__name__) print(" Error message: " + str(e.message))
def brillouin(): '''布里渊区''' return Square(Point(0., 0., 1), numpy.pi * 2.)