コード例 #1
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
コード例 #2
0
def _trapezoid_split(lseg: Segment, sseg: Segment, length):
    '''将一个等腰梯形切分成等边三角形,底和x轴平行\n
    切分六边形的时候,把半和下半都处理成等腰梯形\n
    需要输入等腰梯形的两个底,第一个是比较长的底,第二个是短的,\n
    然后还需要等边三角形的边长
    '''
    assert numpy.isclose(lseg.length - sseg.length, length)
    parts = sseg.length / length
    assert numpy.isclose(parts, numpy.round(parts))
    parts = numpy.int(numpy.round(parts))
    #
    lpt = numpy.ndarray(parts+2, dtype=Point)
    spt = numpy.ndarray(parts+1, dtype=Point)
    #
    spt[0] = sseg.ends[0]
    lpt[0] = lseg.ends[0]
    for idx in range(parts):
        coef = (idx + 1) / parts
        coefb = 1 - coef
        spt[idx+1] = middle_point(sseg.ends[0], sseg.ends[1], coefb, coef)
        coef = (idx + 1) / (parts+1)
        coefb = 1 - coef
        lpt[idx+1] = middle_point(lseg.ends[0], lseg.ends[1], coefb, coef)
    lpt[-1] = lseg.ends[1]
    #pts = numpy.concatenate([spt, lpt])
    #draw_components(pts, [sseg, lseg], [])
    #从长的开始计,第二个点到倒数第二个点
    eqtris = [Eqtriangle([lpt[0], spt[0], lpt[1]])]
    for idx in range(1, parts+1):
        eqtris.append(Eqtriangle([lpt[idx], spt[idx], spt[idx-1]]))
        eqtris.append(Eqtriangle([lpt[idx], spt[idx], lpt[idx+1]]))
    #draw_components(pts, [sseg, lseg], eqtris)
    return eqtris
コード例 #3
0
ファイル: multiband_bubble.py プロジェクト: maryprimary/frg
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
コード例 #4
0
ファイル: triangle.py プロジェクト: maryprimary/frg
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
コード例 #5
0
def eqtriangle_split(eqt: Eqtriangle, nps):
    '''将一个正三角形切分成nps个块'''
    #从两个边开始计算
    #nps条分界线,包含本来的底边
    btmlines = []
    for idx in range(nps):
        coef = (idx+1) / nps
        coefb = 1 - coef
        btmlines.append(
            Segment(
                middle_point(eqt.vertex[0], eqt.vertex[1], coefb, coef),
                middle_point(eqt.vertex[0], eqt.vertex[2], coefb, coef)
            )
        )
    #从这些底边开始切分成新的三角形,找到每条底边上的点
    btmpts = []
    for idx, btml in enumerate(btmlines):
        num = idx + 1
        ptslist = [btml.ends[0]]
        for nid in range(num):
            coef = (nid + 1) / num
            coefb = 1 - coef
            ptslist.append(middle_point(btml.ends[0], btml.ends[1], coefb, coef))
        btmpts.append(ptslist)
    #从上面的点开始,添加新的等边三角形
    eqtris = [Eqtriangle([eqt.vertex[0], btmpts[0][0], btmpts[0][1]])]
    for idx in range(1, nps):
        num = idx + 1
        #每一层有idx+2个点在ptlist里面实际上
        #底在这条线上的三角形
        for ptidx in range(num):
            eqtris.append(
                Eqtriangle(
                    [btmpts[idx-1][ptidx], btmpts[idx][ptidx],btmpts[idx][ptidx+1]]
                )
            )
            #顶在这条线上的三角形
            if ptidx < idx:
                eqtris.append(
                    Eqtriangle(
                        [btmpts[idx-1][ptidx], btmpts[idx][ptidx+1], btmpts[idx-1][ptidx+1]]
                    )
                )
    return btmlines, btmpts, eqtris
コード例 #6
0
def hexagon_split(hexa: Hexagon, nps):
    '''
    将一个六边形切分成小的正三角形
    '''
    #六边形分成两个等腰梯形
    topedge = hexa.edges[1]
    midedge = Segment(hexa.vertex[0], hexa.vertex[3])
    btmedge = hexa.edges[4]
    #所有的小三角形
    eqtris = []
    length = numpy.sum([edg.length for edg in hexa.edges])
    length /= 6
    length /= nps
    #先处理上面半个梯形
    #注意这里由于Hexagon是逆时针对顶点进行的排序
    #所以梯形和三角形增长的方向是从右往左
    llines = [topedge]
    for idx in range(nps):
        coef = (idx + 1) / nps
        coefb = 1 - coef
        llines.append(
            Segment(
                middle_point(topedge.ends[0], midedge.ends[0], coefb, coef),
                middle_point(topedge.ends[1], midedge.ends[1], coefb, coef)
            )
        )
    #llines中一共有nps+1个线
    #注意由于梯形的点是逆时针的,所以这边三角形的增长也是从右向左的
    for idx in range(nps):
        ets = _trapezoid_split(llines[idx+1], llines[idx], length)
        assert len(ets) == 2*nps + 1 + 2*idx
        eqtris.extend(ets)
    #再处理下面半个梯形的
    #这里需要注意下半个梯形的点的顺序问题
    llines = [midedge]
    for idx in range(nps):
        coef = (idx + 1) / nps
        coefb = 1 - coef
        llines.append(
            Segment(
                middle_point(midedge.ends[0], btmedge.ends[1], coefb, coef),
                middle_point(midedge.ends[1], btmedge.ends[0], coefb, coef)
            )
        )
    #llines中共有nps+1条线
    for idx in range(nps):
        ets = _trapezoid_split(llines[idx], llines[idx+1], length)
        assert len(ets) == 4*nps - 1 - 2*idx
        eqtris.extend(ets)
    #开始计算相邻的三角形
    #这个时候,所有的编号都是从右向左,一层一层在增加的
    ladjs = numpy.ndarray(len(eqtris), dtype=object)
    # Warning: 这个ladjs中的相邻的三角形的顺序一定和Eqtriangle的边的顺序是一样的
    #先是nps个上半层,其中三角形的数量是2*nps+1+2*idx
    #idx从0到nps-1
    #先处理最上面的一层的相邻
    #最上面一层就是从[0,2*nps+1)这个范围内的所有
    for idx in range(2*nps+1):
        #每个三角都有三条边,于是有三个相邻
        #这些是底边在下面的相邻的有下一个,和下一行正对的
        #上半部分中,底边在下面的三角形的点是按照右下-上-左下的顺序来的
        if idx % 2 == 0:
            rightone = None if idx == 0 else eqtris[idx-1]
            leftone = None if idx == 2*nps else eqtris[idx+1]
            ladjs[idx] = [rightone, leftone, eqtris[idx+2*nps+2]]
        #这些是底边在上面的,相邻的有上一个和下一个
        #上半部分中,底边在上面的三角形是按照下-左上-右上的顺序来的
        else:
            ladjs[idx] = [eqtris[idx+1], None, eqtris[idx-1]]
    #之后,还有nps-2个上半部分的梯形
    startrange = 2*nps+1
    for npsidx in range(1, nps):
        #startrange是前面0~npsidx-1行包含的数目
        #这行包含的数目
        #如果到了最后一个,下面的一行的三角形的数量和这一行是一样多的
        #计算的时候不需要多添加一个1
        offset = 1 if npsidx != nps-1 else 0
        stoprange = 2*nps+1+2*npsidx
        for idx in range(stoprange):
            tot_idx = startrange + idx
            #这些是底边在下面的相邻的有下一个,和下一行正对的
            #上半部分中,底边在下面的三角形的点是按照右下-上-左下的顺序来的
            if idx % 2 == 0:
                rightone = None if idx == 0 else eqtris[tot_idx-1]
                leftone = None if idx == stoprange - 1 else eqtris[tot_idx+1]
                ladjs[tot_idx] =\
                    [rightone, leftone, eqtris[tot_idx+stoprange+offset]]
            else:
                #上半部分中,底边在上面的三角形是按照下-左上-右上的顺序来的
                ladjs[tot_idx] =\
                    [eqtris[tot_idx+1], eqtris[tot_idx-stoprange+1],\
                        eqtris[tot_idx-1]]
        startrange += stoprange
    #下班部分从后往前开始处理
    #最下面的一个梯形
    for idx in range(2*nps+1):
        #每个三角都有三条边,于是有三个相邻
        #这些是底边在上面的,相邻的有下一个,上面对的,还有上一个
        #下半部分中,底边在上面的三角形是按照右上-下-左上的顺序来的
        tot_idx = len(eqtris) - (2*nps+1) + idx
        if idx % 2 == 0:
            rightone = None if idx == 0 else eqtris[tot_idx-1]
            leftone = None if idx == 2*nps else eqtris[tot_idx+1]
            ladjs[tot_idx] = [rightone, leftone, eqtris[tot_idx-2-2*nps]]
        #下半部分中,底边在下面的三角形是按照上-左下-右下的顺序来的
        else:
            ladjs[tot_idx] = [eqtris[tot_idx+1], None, eqtris[tot_idx-1]]
    startrange = len(eqtris) - (2*nps+1)
    for npsidx in range(1, nps):
        offset = 1 if npsidx != nps-1 else 0
        stoprange = 2*nps+1+2*npsidx
        for idx in range(stoprange):
            tot_idx = startrange - stoprange + idx
            #下半部分中,底边在上面的三角形是按照右上-下-左上的顺序来的
            if idx % 2 == 0:
                rightone = None if idx == 0 else eqtris[tot_idx-1]
                leftone = None if idx == stoprange - 1 else eqtris[tot_idx+1]
                ladjs[tot_idx] = [rightone, leftone, eqtris[tot_idx-offset-stoprange]]
            #下半部分中,底边在下面的三角形是按照上-左下-右下的顺序来的
            else:
                ladjs[tot_idx] = [eqtris[tot_idx+1], eqtris[tot_idx+stoprange-1], eqtris[tot_idx-1]]
        startrange = startrange - stoprange
    return numpy.array(eqtris, dtype=Eqtriangle), ladjs