Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
 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)
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
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
Ejemplo n.º 12
0
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
Ejemplo n.º 13
0
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
Ejemplo n.º 14
0
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
Ejemplo n.º 15
0
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
Ejemplo n.º 16
0
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
Ejemplo n.º 17
0
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
Ejemplo n.º 18
0
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
Ejemplo n.º 19
0
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
Ejemplo n.º 20
0
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
Ejemplo n.º 21
0
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
Ejemplo n.º 22
0
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
Ejemplo n.º 23
0
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
Ejemplo n.º 24
0
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)
Ejemplo n.º 25
0
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))
Ejemplo n.º 26
0
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
Ejemplo n.º 27
0
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
Ejemplo n.º 28
0
def brillouin():
    '''布里渊区'''
    return Hexagon(Point(0, 0, 1), 2*numpy.pi/numpy.sqrt(3))
Ejemplo n.º 29
0
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))
Ejemplo n.º 30
0
def brillouin():
    '''布里渊区'''
    return Square(Point(0., 0., 1), numpy.pi * 2.)