学术源码, 拓扑不变量

陈数Chern number的计算(Wilson loop方法,附Python代码)

这是之前关于陈数的计算:

本篇计算方法见参考资料:https://topocondmat.org/w4_haldane/ComputingChern.html。该方法同样不需要对波函数取连续规范。

为了防止原链接失效,这里截图如下:

下面仍然以这篇“陈数Chern number的计算(定义法,附Python/Matlab代码)”中的哈密顿量为例子,Python程序如下。

一、错误的代码

首先给出一个错误的代码,计算结果的实部是正确的,但虚部的值比较大。这里出错是因为计算一个small plaquettes的Wilson loop时取点的个数太少,仅取了四个点。

"""
This code is supported by the website: https://www.guanjihuan.com
The newest version of this code is on the web page: https://www.guanjihuan.com/archives/18319
"""

"""
Notice that this code is not correct for calculating the Chern number because of the low precision in the calculation of Wilson loop!
"""

import numpy as np
from math import * 
import time
import cmath


def hamiltonian(kx, ky):  # 量子反常霍尔QAH模型(该参数对应的陈数为2)
    t1 = 1.0
    t2 = 1.0
    t3 = 0.5
    m = -1.0
    matrix = np.zeros((2, 2), dtype=complex)
    matrix[0, 1] = 2*t1*cos(kx)-1j*2*t1*cos(ky)
    matrix[1, 0] = 2*t1*cos(kx)+1j*2*t1*cos(ky)
    matrix[0, 0] = m+2*t3*sin(kx)+2*t3*sin(ky)+2*t2*cos(kx+ky)
    matrix[1, 1] = -(m+2*t3*sin(kx)+2*t3*sin(ky)+2*t2*cos(kx+ky))
    return matrix


def main():
    start_time = time.time()
    n = 200  # 积分密度
    delta = 2*pi/n
    chern_number = 0
    for kx in np.arange(-pi, pi, delta):
        for ky in np.arange(-pi, pi, delta):
            H = hamiltonian(kx, ky)
            eigenvalue, eigenvector = np.linalg.eig(H)
            vector = eigenvector[:, np.argsort(np.real(eigenvalue))[0]]  # 价带波函数
            # vector = eigenvector[:, np.argsort(np.real(eigenvalue))[0]]*cmath.exp(1j*np.random.uniform(0, pi))  # 验证规范不依赖性
           
            H_delta_kx = hamiltonian(kx+delta, ky) 
            eigenvalue, eigenvector = np.linalg.eig(H_delta_kx)
            vector_delta_kx = eigenvector[:, np.argsort(np.real(eigenvalue))[0]]   # 略偏离kx的波函数

            H_delta_ky = hamiltonian(kx, ky+delta)  
            eigenvalue, eigenvector = np.linalg.eig(H_delta_ky)
            vector_delta_ky = eigenvector[:, np.argsort(np.real(eigenvalue))[0]]  # 略偏离ky的波函数

            H_delta_kx_ky = hamiltonian(kx+delta, ky+delta)  
            eigenvalue, eigenvector = np.linalg.eig(H_delta_kx_ky)
            vector_delta_kx_ky = eigenvector[:, np.argsort(np.real(eigenvalue))[0]]  # 略偏离kx和ky的波函数

            line_1 = np.dot(vector.transpose().conj(), vector_delta_kx)
            line_2 = np.dot(vector_delta_kx.transpose().conj(), vector_delta_kx_ky)
            line_3 = np.dot(vector_delta_kx_ky.transpose().conj(), vector_delta_ky)
            line_4 = np.dot(vector_delta_ky.transpose().conj(), vector)

            arg = np.log(np.dot(np.dot(np.dot(line_1, line_2), line_3), line_4))/1j
            chern_number = chern_number + arg
    chern_number = chern_number/(2*pi)
    print('Chern number = ', chern_number)
    end_time = time.time()
    print('运行时间(秒)=', end_time-start_time)


if __name__ == '__main__':
    main()

运行结果:

Chern number = (2.0000000000000013+2.6085429982998165j)

二、正确的代码

"""
This code is supported by the website: https://www.guanjihuan.com
The newest version of this code is on the web page: https://www.guanjihuan.com/archives/18319
"""

import numpy as np
from math import * 
import time
import cmath


def hamiltonian(kx, ky):  # 量子反常霍尔QAH模型(该参数对应的陈数为2)
    t1 = 1.0
    t2 = 1.0
    t3 = 0.5
    m = -1.0
    matrix = np.zeros((2, 2), dtype=complex)
    matrix[0, 1] = 2*t1*cos(kx)-1j*2*t1*cos(ky)
    matrix[1, 0] = 2*t1*cos(kx)+1j*2*t1*cos(ky)
    matrix[0, 0] = m+2*t3*sin(kx)+2*t3*sin(ky)+2*t2*cos(kx+ky)
    matrix[1, 1] = -(m+2*t3*sin(kx)+2*t3*sin(ky)+2*t2*cos(kx+ky))
    return matrix


def main():
    start_time = time.time()
    n1 = 10 # small plaquettes精度
    n2 = 800 # Wilson loop精度
    delta = 2*pi/n1
    chern_number = 0
    for kx in np.arange(-pi, pi, delta):
        for ky in np.arange(-pi, pi, delta):
            vector_array = []
            # line_1
            for i2 in range(n2+1):
                H_delta = hamiltonian(kx+delta/n2*i2, ky) 
                eigenvalue, eigenvector = np.linalg.eig(H_delta)
                vector_delta = eigenvector[:, np.argsort(np.real(eigenvalue))[0]]
                # vector_delta = eigenvector[:, np.argsort(np.real(eigenvalue))[0]]*cmath.exp(1j*np.random.uniform(0, pi))  # 验证规范不依赖性
                vector_array.append(vector_delta)
            # line_2
            for i2 in range(n2):
                H_delta = hamiltonian(kx+delta, ky+delta/n2*(i2+1))  
                eigenvalue, eigenvector = np.linalg.eig(H_delta)
                vector_delta = eigenvector[:, np.argsort(np.real(eigenvalue))[0]]
                vector_array.append(vector_delta)
            # line_3
            for i2 in range(n2):
                H_delta = hamiltonian(kx+delta-delta/n2*(i2+1), ky+delta)  
                eigenvalue, eigenvector = np.linalg.eig(H_delta)
                vector_delta = eigenvector[:, np.argsort(np.real(eigenvalue))[0]]
                vector_array.append(vector_delta)
            # line_4
            for i2 in range(n2-1):
                H_delta = hamiltonian(kx, ky+delta-delta/n2*(i2+1))  
                eigenvalue, eigenvector = np.linalg.eig(H_delta)
                vector_delta = eigenvector[:, np.argsort(np.real(eigenvalue))[0]]
                vector_array.append(vector_delta)
            Wilson_loop = 1
            for i0 in range(len(vector_array)-1):
                Wilson_loop = Wilson_loop*np.dot(vector_array[i0].transpose().conj(), vector_array[i0+1])
            Wilson_loop = Wilson_loop*np.dot(vector_array[len(vector_array)-1].transpose().conj(), vector_array[0])
            arg = np.log(Wilson_loop)/1j
            chern_number = chern_number + arg
    chern_number = chern_number/(2*pi)
    print('Chern number = ', chern_number)
    end_time = time.time()
    print('运行时间(秒)=', end_time-start_time)


if __name__ == '__main__':
    main()

运行结果:

Chern number = (1.9999999999999987+0.0032600066414606387j)

随着Wilson loop计算精度的提高,虚部将趋于0。

其他参考资料:

[1] 数学上陈数(Chern number)或 Berry Phase 有何意义?

[2] 贝里相位、贝里联络、贝里曲率和陈数

[3] B. Andrei Bernevig - Topological Insulators and Topological Superconductors 第30页

【未经同意请勿转载。引用请注明出处:https://www.guanjihuan.com

1,414 次浏览

9 thoughts on “陈数Chern number的计算(Wilson loop方法,附Python代码)”

  1. 请问计算Wilson loop 的时候,最后为什么要进行这一行操作?
    Wilson_loop = ilson_loop*np.dot(vector_array[len(vector_array)-1].transpose().conj(), vector_array[0])。 end的波函数再与begin的波函数dot?

    在计算SSH Wilson loop的时候,让begin的波函数与end的波函数相等,并没有这一步操作。

    1. Wilson loop就是要首尾相连的。在计算SSH的Wilson loop中,也是有首尾相连,对于布里渊区来说,k=-pi和k=pi实际上是同一点,和end的波函数内积,就相当于和begin的波函数内积。为了在数值上避开波函数的规范问题,所以令end的波函数和begin的波函数相等。

  2. 博主您好,我想问一下,我修改plaquettes精度会影响陈数的值,差几倍的那种,这有可能是什么原因呢?谢谢~

    1. 尽量还是取大一点吧,只要数值能收敛就没有太大问题。但如果增大精度数值一直不收敛,那计算结果可能就不对了。

    1. 参考前面几篇的方法。这里的方法,我还没明白为什么结果的虚部会这么大。按理来说,应该为无穷小。

      1. 实陈数的化我们是否是在berry curvature那里加一个-i*σy,然后求个trace呢,这样操作后感觉有问题

        1. 找到问题的原因了,是因为计算Wilson loop时,取的点太少了。已更新最新的代码。

发表评论

您的电子邮箱地址不会被公开。