这篇博客中利用另外一种格林函数的方法来计算拓扑绝缘体的边界态.
{:.info}

在前面利用格林函数求解边界态这篇博客中利用迭代格林函数的方法计算了拓扑绝缘体的边界态,但是结果中边界态的确很明显,但是体态的性质却不会表现的很清晰,这里就像利用矩阵求逆的方式,直接计算哈密顿量对应的谱函数,从而来计算边界态和体态的性质,但是这个方法的缺点也是比较明显的,那就是耗时比较长.

模型

仍然以拓扑绝缘体的哈密顿量为出发点

对这个哈密顿量沿着$x$方向取开边界,沿$y$方向仍然是周期边界条件,这样就可以在一个圆柱结构上计算边界态了,对应的谱函数为

这里的$H(\mathbf{k})$是开边界之后的哈密顿量.

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
    module pub
implicit none
integer yn,kn,ne,N,enn,hn
real eta,dk,de
parameter(yn = 50,hn = 4,kn = 50, ne = 50,N = yn*4,eta = 0.01,dk = 0.01,de = dk)
real,parameter::pi = 3.1415926535
complex,parameter::im = (0.,1.0)
complex Ham(N,N),one(N,N)
!=================================
real m0,mu
real tx,ty
real ax,ay,gamma
complex g1(hn,hn)
complex g2(hn,hn)
complex g3(hn,hn)
!================cheev===============
integer::lda = N
integer,parameter::lwmax = 2*N + N**2
real,allocatable::w(:)
complex,allocatable::work(:)
real,allocatable::rwork(:)
integer,allocatable::iwork(:)
integer lwork
integer lrwork
integer liwork
integer info
end module pub
!================= PROGRAM START ============================
program sol
use pub
integer i1
!====空间申请==================
allocate(w(N))
allocate(work(lwmax))
allocate(rwork(1+5*N+2*N**2))
allocate(iwork(3+5*N))
!======parameter value setting =====
m0 = 1.5
mu = 0
tx = 1.0
ty = 1.0
ax = 1.0
ay = 1.0
do i1 = 1,N
one(i1,i1) = 1 !单位矩阵
end do
call main()
stop
end program sol
!=============================================================================================
subroutine main()
! Calculate edge spectrum function
use pub
integer m1,m2,i1
real kx,ky,omega,re2
complex h1(N,N),h2(N,N)
complex re1
open(30,file="openy-bhz.dat")
!-------------------------------------------------
! y-direction is open
do omega = -3.0,3.0,de
do kx = -pi,pi,dk
re1 = 0
call openy(kx)
h1 = omega*one - ham + im*eta*one
call inv(h1,h2)
do i1 = 1,N
re1 = re1 + h2(i1,i1)
end do
re2 = -2*aimag(re1)/pi/N
write(30,999)kx/pi,omega,re2
end do
write(30,*)" "
end do
close(30)
!---------------------------------------------------------------------
! x-direction is open
open(31,file="openx-bhz.dat")
do omega = -3.0,3.0,de
do ky = -pi,pi,dk
re1 = 0
call openx(ky)
h1 = omega*one - ham + im*eta*one
call inv(h1,h2)
do i1 = 1,N
re1 = re1 + h2(i1,i1)
end do
re2 = -2*aimag(re1)/pi/N
write(31,999)ky/pi,omega,re2
end do
write(31,*)" "
end do
close(31)
999 format(3f11.5)
return
end subroutine main
!======================== Pauli Matrix driect product============================
subroutine Pauli()
use pub
! TI
!=== Kinetic energy
g1(1,1) = 1
g1(2,2) = -1
g1(3,3) = 1
g1(4,4) = -1
!====== SOC-x
g2(1,2) = 1
g2(2,1) = 1
g2(3,4) = -1
g2(4,3) = -1
!====== SOC-y
g3(1,2) = -im
g3(2,1) = im
g3(3,4) = -im
g3(4,3) = im
return
end subroutine Pauli
!==========================================================
subroutine openx(ky)
use pub
real ky
integer m,l,k
call Pauli()
Ham = 0
!========== Positive energy ========
do k = 0,yn-1
if (k == 0) then ! Only right block in first line
do m = 1,hn
do l = 1,hn
Ham(m,l) = (m0-ty*cos(ky))*g1(m,l) + ay*sin(ky)*g3(m,l)

Ham(m,l + hn) = (-tx*g1(m,l) - im*ax*g2(m,l))/2
end do
end do
elseif ( k==yn-1 ) then ! Only left block in last line
do m = 1,hn
do l = 1,hn
Ham(k*hn + m,k*hn + l) = (m0-ty*cos(ky))*g1(m,l) + ay*sin(ky)*g3(m,l)

Ham(k*hn + m,k*hn + l - hn) = -tx*g1(m,l)/2 + im*ax*g2(m,l)/2
end do
end do
else
do m = 1,hn
do l = 1,hn ! k start from 1,matrix block from 2th row
Ham(k*hn + m,k*hn + l) = (m0 - ty*cos(ky))*g1(m,l) + ay*sin(ky)*g3(m,l)

Ham(k*hn + m,k*hn + l + hn) = (-tx*g1(m,l) - im*ax*g2(m,l))/2
Ham(k*hn + m,k*hn + l - hn) = -tx*g1(m,l)/2 + im*ax*g2(m,l)/2
end do
end do
end if
end do
!------------------------
call isHermitian()
! call eigsol()
return
end subroutine openx
!==========================================================
subroutine openy(kx)
use pub
real kx
integer m,l,k
call Pauli()
Ham = 0
!========== Positive energy ========
do k = 0,yn-1
if (k == 0) then ! Only right block in first line
do m = 1,hn
do l = 1,hn
Ham(m,l) = (m0-tx*cos(kx))*g1(m,l) + ax*sin(kx)*g2(m,l)

Ham(m,l + hn) = (-ty*g1(m,l) - im*ay*g3(m,l))/2
end do
end do
elseif ( k==yn-1 ) then ! Only left block in last line
do m = 1,hn
do l = 1,hn
Ham(k*hn + m,k*hn + l) = (m0-tx*cos(kx))*g1(m,l) + ax*sin(kx)*g2(m,l)

Ham(k*hn + m,k*hn + l - hn) = -ty*g1(m,l)/2 + im*ay*g3(m,l)/2
end do
end do
else
do m = 1,hn
do l = 1,hn ! k start from 1,matrix block from 2th row
Ham(k*hn + m,k*hn + l) = (m0-tx*cos(kx))*g1(m,l) + ax*sin(kx)*g2(m,l)

Ham(k*hn + m,k*hn + l + hn) = (-ty*g1(m,l) - im*ay*g3(m,l) )/2
Ham(k*hn + m,k*hn + l - hn) = -ty*g1(m,l)/2 + im*ay*g3(m,l)/2
end do
end do
end if
end do
!---------------------------------
call isHermitian()
! call eigsol()
return
end subroutine openy
!============================================================
subroutine isHermitian()
use pub
integer i,j
do i = 1,N
do j = 1,N
if (Ham(i,j) .ne. conjg(Ham(j,i)))then
open(160,file = 'hermitian.dat')
write(160,*)i,j
write(160,*)Ham(i,j)
write(160,*)Ham(j,i)
write(160,*)"===================="
write(*,*)"Hamiltonian is not hermitian"
stop
end if
end do
end do
close(160)
return
end subroutine isHermitian
!================= 矩阵本征值求解 ==============
subroutine eigSol()
use pub
integer m
lwork = -1
liwork = -1
lrwork = -1
call cheevd('V','Upper',N,Ham,lda,w,work,lwork &
,rwork,lrwork,iwork,liwork,info)
lwork = min(2*N+N**2, int( work( 1 ) ) )
lrwork = min(1+5*N+2*N**2, int( rwork( 1 ) ) )
liwork = min(3+5*N, iwork( 1 ) )
call cheevd('V','Upper',N,Ham,lda,w,work,lwork &
,rwork,lrwork,iwork,liwork,info)
if( info .GT. 0 ) then
open(110,file="mes.dat",status="unknown")
write(110,*)'The algorithm failed to compute eigenvalues.'
close(110)
end if
! open(120,file="eigval.dat")
! do m = 1,N
! write(120,*)w(m)
! end do
! close(120)
return
end subroutine eigSol
!=================================================================
subroutine inv(matin,matout)
use pub
complex,intent(in) :: matin(N,N)
complex:: matout(size(matin,1),size(matin,2))
real:: work2(size(matin,1)) ! work array for LAPACK
integer::info2,ipiv(size(matin,1)) ! pivot indices
! Store A in Ainv to prevent it from being overwritten by LAPACK
matout = matin
! SGETRF computes an LU factorization of a general M-by-N matrix A
! using partial pivoting with row interchanges.
call CGETRF(N,N,matout,N,ipiv,info2)
if (info2.ne.0)then
write(*,*)'Matrix is numerically singular!'
stop
end if
! SGETRI computes the inverse of a matrix using the LU factorization
! computed by SGETRF.
call CGETRI(N,matout,N,ipiv,work2,N,info2)
if (info2.ne.0)then
write(*,*)'Matrix inversion failed!'
stop
end if
return
end subroutine inv

编译命令

1
ifort -mkl file.f90

绘图

因为想要看到清晰的结果,在离散撒点的时候,间隔必须很小,那么数据文件就会很大,这里推荐gnuplot绘图,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
set encoding iso_8859_1
#set terminal postscript enhanced color
#set output 'arc_r.eps'
#set terminal pngcairo truecolor enhanced font ",50" size 1920, 1680
set terminal png truecolor enhanced font ",50" size 1920, 1680
set output 'density.png'
#set palette defined ( -10 "#194eff", 0 "white", 10 "red" )
set palette defined ( -10 "blue", 0 "white", 10 "red" )
#set palette rgbformulae 33,13,10
unset ztics
unset key
set pm3d
set border lw 6
set size ratio 1
set view map
set xtics
set ytics
#set xlabel "K_1 (1/{\305})"
set xlabel "X_1"
#set ylabel "K_2 (1/{\305})"
set ylabel "Y"
set ylabel offset 1, 0
set colorbox
set xrange [-1:1]
set yrange [-3:3]
set pm3d interpolate 4,4
#splot 'wavenorm.dat' u 1:2:3 w pm3d
#splot 'wavenorm.dat' u 1:2:3 w pm3d
splot 'openy-bhz.dat' u 1:2:3 w pm3d

绘图

1
gnuplot file.gnu

最后的结果为

png

相比较于利用格林函数求解边界态中的结果,可以清晰的看到边界态和体态的结果.如果接的图中的颜色并不能很好的展现,可以在gnuplot绘图中修改颜色方案

1
set palette defined ( -10 "white", 0 "blue", 10 "red" )

在新的配色方案中,边界态就可以很清晰的表现出来
png

代码下载

点击这里下载代码.

公众号

相关内容均会在公众号进行同步,若对该Blog感兴趣,欢迎关注微信公众号。
{:.info}

QR Code

Email

yxliphy@gmail.com