学术源码, 模型和能带

以SSH模型为例子说明两种傅里叶变换方法

这篇“离散格子的傅里叶变换和反傅里叶变换”提到两种傅里叶变换方法(两种规范):

傅里叶变换时坐标可以用实际原子坐标,也可以用元胞坐标。用原子坐标时,傅里叶变量元胞内有些跃迁项会增加相位,即 e^{ika_{in}};而用元胞坐标时,傅里叶变换元胞内就没有增加相位,即e^{0}。两种方法计算的结果是一样的,但建议用元胞坐标,会更方便些,尤其是当元胞比较大的时候会简单很多。

这里以SSH模型为例子进行说明。这是之前的一篇:SSH模型的哈密顿量、能带图和卷绕数(附Python代码)。示意图为:

实空间哈密顿量:

H=v\sum\limits_{m=1}^{N}(|m, B\rangle \langle m, A|+h.c.)+w\sum\limits_{m=1}^{N-1}(|m+1, A\rangle \langle m,B|+h.c.)

1. 以元胞为单元的傅里叶变换

傅里叶变换过程参考:离散格子的傅里叶变换和反傅里叶变换

第一项傅里叶变换后得到:

H_1=\nu\sum\limits_k(|k, B\rangle\langle k, A|+h.c.)

第二项傅里叶变换后得到:

H_2=w\sum\limits_k(e^{-ik(2a)}|k, A\rangle\langle k, B|+h.c.)

其中,a为原子间距。令2a=1,因此哈密顿量写为:

H(k)=\begin{pmatrix}0 & \nu+w e^{-ik} \\\nu+w e^{ik} & 0\end{pmatrix}

2. 以原子为单元的傅里叶变换

第一项傅里叶变换后得到:

H_1=\nu\sum\limits_k(e^{ka}|k, B\rangle\langle k, A|+h.c.)

第二项傅里叶变换后得到:

H_2=w\sum\limits_k(e^{-ika}|k, A\rangle\langle k, B|+h.c.)

其中,a为原子间距。 令2a=1,因此哈密顿量写为:

H(k)= \begin{pmatrix}0 & \nu  e^{ik \frac{1}{2}}+w e^{-ik \frac{1}{2} } \\\nu  e^{-ik \frac{1}{2}} +w e^{ik \frac{1}{2} } & 0\end{pmatrix}

3. 本征值等价验证

(1)表达式验证

参考“由泡利矩阵组成的哈密顿量的本征值”,第一个哈密顿量形式的本征值为:

E_1=\pm \sqrt{(\nu+w \cos k)^2+(w \sin k)^2}=\pm \sqrt{\nu^2+w^2+2\nu w \cos k}

第二个哈密顿量形式的本征值:

\begin{aligned}E_2&=\pm \sqrt{(v\cos (\frac{1}{2}k)+w\cos(\frac{1}{2}k))^2+ (v\sin(-\frac{1}{2}k)+w\sin( \frac{1}{2}k))^2}\\& =\pm \sqrt{(v+w)^2 \cos^2(\frac{1}{2}k)+ (-v+w)^2 \sin^2(\frac{1}{2}k)  }\\&=\pm \sqrt{ \nu^2+w^2+2\nu w \cos k }  \end{aligned}

(2)数值验证

代码如下(可以用到开源软件包Guan:https://py.guanjihuan.com):

"""
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/16199
"""

import numpy as np
from math import *
import cmath

def hamiltonian_1(k, v=0.6, w=1):
    matrix = np.zeros((2, 2), dtype=complex)
    matrix[0,1] = v+w*cmath.exp(-1j*k)
    matrix[1,0] = v+w*cmath.exp(1j*k)
    return matrix

def hamiltonian_2(k, v=0.6, w=1):
    matrix = np.zeros((2, 2), dtype=complex)
    matrix[0,1] = v*cmath.exp(1j*k/2)+w*cmath.exp(-1j*k/2)
    matrix[1,0] = v*cmath.exp(-1j*k/2)+w*cmath.exp(1j*k/2)
    return matrix

def main():
    k_array = np.linspace(-pi ,pi, 100)
    E_1_array = calculate_eigenvalue_with_one_parameter(k_array, hamiltonian_1)
    plot(k_array, E_1_array, xlabel='k', ylabel='E_1')
    E_2_array = calculate_eigenvalue_with_one_parameter(k_array, hamiltonian_2)
    plot(k_array, E_2_array, xlabel='k', ylabel='E_2')

    # import guan
    # E_1_array = guan.calculate_eigenvalue_with_one_parameter(k_array, hamiltonian_1)
    # guan.plot(k_array, E_1_array, xlabel='k', ylabel='E_1')
    # E_2_array = guan.calculate_eigenvalue_with_one_parameter(k_array, hamiltonian_2)
    # guan.plot(k_array, E_2_array, xlabel='k', ylabel='E_2')

def calculate_eigenvalue_with_one_parameter(x_array, hamiltonian_function, print_show=0):
    dim_x = np.array(x_array).shape[0]
    i0 = 0
    if np.array(hamiltonian_function(0)).shape==():
        eigenvalue_array = np.zeros((dim_x, 1))
        for x0 in x_array:
            hamiltonian = hamiltonian_function(x0)
            eigenvalue_array[i0, 0] = np.real(hamiltonian)
            i0 += 1
    else:
        dim = np.array(hamiltonian_function(0)).shape[0]
        eigenvalue_array = np.zeros((dim_x, dim))
        for x0 in x_array:
            if print_show==1:
                print(x0)
            hamiltonian = hamiltonian_function(x0)
            eigenvalue, eigenvector = np.linalg.eigh(hamiltonian)
            eigenvalue_array[i0, :] = eigenvalue
            i0 += 1
    return eigenvalue_array

def plot(x_array, y_array, xlabel='x', ylabel='y', title='', fontsize=20, labelsize=20, show=1, save=0, filename='a', format='jpg', dpi=300, style='', y_min=None, y_max=None, linewidth=None, markersize=None, adjust_bottom=0.2, adjust_left=0.2): 
    import matplotlib.pyplot as plt
    fig, ax = plt.subplots()
    plt.subplots_adjust(bottom=adjust_bottom, left=adjust_left) 
    ax.plot(x_array, y_array, style, linewidth=linewidth, markersize=markersize)
    ax.grid()
    ax.set_title(title, fontsize=fontsize, fontfamily='Times New Roman')
    ax.set_xlabel(xlabel, fontsize=fontsize, fontfamily='Times New Roman') 
    ax.set_ylabel(ylabel, fontsize=fontsize, fontfamily='Times New Roman') 
    if y_min!=None or y_max!=None:
        if y_min==None:
            y_min=min(y_array)
        if y_max==None:
            y_max=max(y_array)
        ax.set_ylim(y_min, y_max)
    ax.tick_params(labelsize=labelsize) 
    labels = ax.get_xticklabels() + ax.get_yticklabels()
    [label.set_fontname('Times New Roman') for label in labels]
    if save == 1:
        plt.savefig(filename+'.'+format, dpi=dpi) 
    if show == 1:
        plt.show()
    plt.close('all')

if __name__ == '__main__':
    main()

计算结果:两个图相同。

4. 键长不同的情况

根据评论补充:当元胞内部的原子距离和元胞间距离不同时,即a1不等于a2,此时两种方法的结果也是一样,前提是统一标准,例如间距a1+a2=1。数值和解析均可以验证。解析推导要用到余弦公式Cos(x+y)=CosxCosy-SinxSiny。以下是具体推导。

不妨令a1+a2=1,哈密顿量的第一种形式:

H(k)=\begin{pmatrix}0 & \nu+w e^{-ik(a_1+a_2)} \\\nu+w e^{ik(a_1+a_2)} & 0\end{pmatrix}=\begin{pmatrix}0 & \nu+w e^{-ik} \\\nu+w e^{ik} & 0\end{pmatrix}

哈密顿量的第二种形式:

H(k)= \begin{pmatrix}0 & \nu  e^{ik a_1}+w e^{-ik a_2 } \\\nu  e^{-ik a_1} +w e^{ik a_2 } & 0\end{pmatrix}

第一个形式和之前的相同,本征值也和之前的相同。

第二个形式的本征值为:

\begin{aligned}E_2&=\pm \sqrt{(v\cos (ka_1)+w\cos( ka_2))^2+ (v\sin(-ka_1)+w\sin( ka_2))^2}\\& =\pm \sqrt{(v+w)^2 +2vw\cos(ka_1)\cos(ka_2)-2vw\sin(ka_1)\sin(ka_2) }\\&=\pm \sqrt{ \nu^2+w^2+2\nu w \cos [k(a_1+a_2)] } \\&=\pm \sqrt{ \nu^2+w^2+2\nu w \cos k}  \end{aligned}

本征值相同。

参考资料:

[1] 六角蜂窝格子紧束缚模型的计算

[2] WannierTools: An open-source software package for novel topological materials

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

1,381 次浏览

6 thoughts on “以SSH模型为例子说明两种傅里叶变换方法”

    1. 方法和上面是一样的呀,把两个1/2分别用a1和a2来代替,同样再算一下,结果是一样的,不需要其他参考资料了。

  1. 您好,假如元胞内部的原子距离和元胞间距离不同时是不是只能选用第二种方法?

    1. 即使a1不等于a2时,两种方法的结果也是一样,前提是统一标准,例如间距a1+a2=1。我数值和解析都验证过了,没问题的。

      解析推导要用到余弦公式Cos(x+y)=CosxCosy-SinxSiny。

发表评论

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