Skip to content

Commit 3036070

Browse files
authored
Merge pull request #178 from zhangyan31415/support_nonorth
feat: add non-orthogonal basis support
2 parents 108344f + d95e144 commit 3036070

File tree

8 files changed

+582
-72
lines changed

8 files changed

+582
-72
lines changed

src/ek_bulk.f90

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ subroutine ek_bulk_line
2121
real(Dp), allocatable :: W(:)
2222

2323
! Hamiltonian of bulk system
24-
complex(Dp), allocatable :: Hamk_bulk(:, :)
24+
complex(Dp), allocatable :: Hamk_bulk(:, :), Sk_bulk(:, :)
2525

2626
! eigenectors of H
2727
real(dp), allocatable :: eigv(:,:), eigv_mpi(:,:)
@@ -39,6 +39,10 @@ subroutine ek_bulk_line
3939
eigv = 0d0; eigv_mpi= 0d0
4040
weight = 0d0; weight_sum = 0d0; weight_mpi = 0d0
4141

42+
if (.not. Orthogonal_Basis) then
43+
allocate(Sk_bulk(Num_wann, Num_wann))
44+
Sk_bulk= 0d0
45+
endif
4246

4347
do ik= 1+cpuid, knv3, num_cpu
4448

@@ -55,7 +59,20 @@ subroutine ek_bulk_line
5559
if (index(Particle,'phonon')/=0.and.LOTO_correction) then
5660
call ham_bulk_LOTO(k, Hamk_bulk)
5761
else
58-
call ham_bulk_latticegauge(k, Hamk_bulk)
62+
if (Is_Sparse) then
63+
stop 'ERROR: Sparse mode is not supported in ek_bulk_line'
64+
else
65+
if (Orthogonal_Basis) then
66+
call ham_bulk_latticegauge(k, Hamk_bulk)
67+
else
68+
69+
Sk_bulk= 0d0
70+
call S_bulk_latticegauge(k, Sk_bulk)
71+
call ham_bulk_latticegauge(k, Hamk_bulk)
72+
call orthogonalize_hamiltonian(Hamk_bulk, Sk_bulk, Num_wann)
73+
endif
74+
75+
endif
5976
!call ham_bulk_atomicgauge(k, Hamk_bulk)
6077
endif
6178
endif
@@ -3407,7 +3424,7 @@ subroutine generate_ek_kpath_gnu(datafilename, gnufilename, gnuoutfilename, &
34073424
endif
34083425
enddo
34093426
write(outfileindex, '(2a)')"# please comment the following lines to plot the fatband "
3410-
if (Is_Sparse_Hr) then
3427+
if (Is_Sparse) then
34113428
write(outfileindex, '(4a)')"plot '", trim(adjustl(datafilename)), "' u 1:2 ", &
34123429
" w p pt 7 ps 0.2 lc rgb 'black', 0 w l lw 2 dt 2"
34133430
else

src/ham_bulk.f90

Lines changed: 133 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -402,21 +402,143 @@ subroutine ham_bulk_latticegauge(k,Hamk_bulk)
402402
!Hamk_bulk= (Hamk_bulk+ mat2)/2d0
403403

404404
! check hermitcity
405-
!do i1=1, Num_wann
406-
! do i2=1, Num_wann
407-
! if(abs(Hamk_bulk(i1,i2)-conjg(Hamk_bulk(i2,i1))).ge.1e-6)then
408-
! write(stdout,*)'there is something wrong with Hamk_bulk'
409-
! write(stdout,*)'i1, i2', i1, i2
410-
! write(stdout,*)'value at (i1, i2)', Hamk_bulk(i1, i2)
411-
! write(stdout,*)'value at (i2, i1)', Hamk_bulk(i2, i1)
412-
! !stop
413-
! endif
414-
! enddo
415-
!enddo
405+
!打印出k点
406+
! write(*,*)'check Hamk_bulk hermitcity'
407+
do i1=1, Num_wann
408+
do i2=1, Num_wann
409+
if(abs(Hamk_bulk(i1,i2)-conjg(Hamk_bulk(i2,i1))).ge.1e-6)then
410+
write(stdout,*)'there is something wrong with Hamk_bulk'
411+
write(stdout,*)'i1, i2', i1, i2
412+
write(stdout,*)'value at (i1, i2)', Hamk_bulk(i1, i2)
413+
write(stdout,*)'value at (i2, i1)', Hamk_bulk(i2, i1)
414+
!stop
415+
endif
416+
enddo
417+
enddo
416418

417419
return
418420
end subroutine ham_bulk_latticegauge
419421

422+
423+
subroutine S_bulk_latticegauge(k,Sk_bulk)
424+
! This subroutine caculates Hamiltonian for
425+
! bulk system without the consideration of the atom's position
426+
!
427+
! History
428+
!
429+
! May/29/2011 by Quansheng Wu
430+
431+
use para, only : dp, pi2zi, SmnR, ndegen, nrpts, irvec, Num_wann, stdout, twopi, zi
432+
implicit none
433+
434+
! loop index
435+
integer :: i1,i2,iR
436+
437+
real(dp) :: kdotr
438+
439+
complex(dp) :: factor
440+
441+
real(dp), intent(in) :: k(3)
442+
443+
! Hamiltonian of bulk system
444+
complex(Dp),intent(out) ::Sk_bulk(Num_wann, Num_wann)
445+
446+
Sk_bulk=0d0
447+
do iR=1, Nrpts
448+
kdotr= k(1)*irvec(1,iR) + k(2)*irvec(2,iR) + k(3)*irvec(3,iR)
449+
factor= (cos(twopi*kdotr)+zi*sin(twopi*kdotr))
450+
451+
Sk_bulk(:, :)= Sk_bulk(:, :)+ SmnR(:, :, iR)*factor
452+
enddo ! iR
453+
454+
!call mat_mul(Num_wann, mirror_z, Hamk_bulk, mat1)
455+
!call mat_mul(Num_wann, mat1, mirror_z, mat2)
456+
!Hamk_bulk= (Hamk_bulk+ mat2)/2d0
457+
458+
! check hermitcity
459+
! write(*,*)'check Sk_bulk'
460+
do i1=1, Num_wann
461+
do i2=1, Num_wann
462+
if(abs(Sk_bulk(i1,i2)-conjg(Sk_bulk(i2,i1))).ge.1e-6)then
463+
write(stdout,*)'there is something wrong with Sk_bulk'
464+
write(stdout,*)'i1, i2', i1, i2
465+
write(stdout,*)'value at (i1, i2)', Sk_bulk(i1, i2)
466+
write(stdout,*)'value at (i2, i1)', Sk_bulk(i2, i1)
467+
!stop
468+
endif
469+
enddo
470+
enddo
471+
472+
return
473+
end subroutine S_bulk_latticegauge
474+
475+
!---------------------------------------------------------------
476+
! Surroutines:change the non-orthogonal basis H and S to orthogonal basis
477+
! H_new = U * H_old * U
478+
! U = S_vec * M_inv * S_vec^H
479+
!---------------------------------------------------------------
480+
subroutine orthogonalize_hamiltonian(Hamk_bulk, Sk_bulk , N)
481+
use para, only: Dp, stdout,E_fermi,eV2Hartree
482+
implicit none
483+
484+
integer, intent(in) :: N
485+
complex(Dp), intent(in ) :: Sk_bulk(N,N)
486+
complex(Dp), intent(inout) :: Hamk_bulk(N,N)
487+
488+
!-- 局部 --
489+
integer :: i, info, j
490+
real(Dp), allocatable :: S_vals(:)
491+
complex(Dp), allocatable :: S_vec(:,:), M_inv(:,:), U(:,:)
492+
493+
494+
allocate(S_vals(N))
495+
allocate(S_vec (N,N))
496+
allocate(M_inv (N,N))
497+
allocate(U (N,N))
498+
U = (0.0_dp,0.0_dp)
499+
! 1) Sk_bulk = S_vec * diag(S_vals) * S_vec^H
500+
S_vec = Sk_bulk
501+
call eigensystem_c('V','U', N, S_vec, S_vals)
502+
503+
! 2) M_inv = diag(1/√S_vals)
504+
M_inv = (0.0_dp,0.0_dp)
505+
! do i = 1, N
506+
! M_inv(i,i) = 1.0_dp / sqrt(S_vals(i))
507+
! end do
508+
509+
do i = 1, N
510+
if (S_vals(i) <= 0.0_dp) then
511+
write(stdout,'(a,i5,1pe13.4)') ' WARNING: λ <= 0, i =', i, S_vals(i)
512+
else
513+
M_inv(i,i) = 1.0_dp / sqrt(S_vals(i))
514+
endif
515+
enddo
516+
517+
! 3) U = S_vec * M_inv * S_vec^H
518+
! U = matmul( S_vec, matmul(M_inv, conjg(transpose(S_vec))) )
519+
U = matmul( S_vec, M_inv )
520+
U = matmul(U, conjg(transpose(S_vec)))
521+
522+
! call mat_mul(N, S_vec, M_inv, U)
523+
! call mat_mul(N, U, conjg(transpose(S_vec)), U)
524+
525+
526+
! 4)Hamiltonian = U * Hamk_bulk * U
527+
! Hamk_bulk = matmul( U, matmul(Hamk_bulk, U) )
528+
Hamk_bulk = matmul(U, Hamk_bulk)
529+
Hamk_bulk = matmul(Hamk_bulk, U)
530+
! call mat_mul(N, U, Hamk_bulk, Hamk_bulk)
531+
! call mat_mul(N, Hamk_bulk, U, Hamk_bulk)
532+
533+
do i = 1, N
534+
Hamk_bulk(i,i) = Hamk_bulk(i,i) - E_fermi*eV2Hartree
535+
enddo
536+
537+
deallocate(S_vals, S_vec, M_inv, U)
538+
end subroutine orthogonalize_hamiltonian
539+
540+
541+
420542
subroutine dHdk_latticegauge_wann(k, velocity_Wannier)
421543
use para, only : Nrpts, irvec, crvec, Origin_cell, &
422544
HmnR, ndegen, Num_wann, zi, pi2zi, dp, twopi

src/ham_qlayer2qlayer.f90

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,110 @@ subroutine ham_qlayer2qlayer(k,H00new,H01new)
101101
return
102102
end subroutine ham_qlayer2qlayer
103103

104+
subroutine s_qlayer2qlayer(k,H00new,H01new)
105+
! This subroutine caculates Hamiltonian between
106+
! slabs For surface state calculation
107+
! 4/23/2010 by QS Wu
108+
! Copyright (c) 2010 QuanSheng Wu. All rights reserved.
109+
110+
use para
111+
112+
implicit none
113+
114+
! loop index
115+
integer :: i,j,iR
116+
117+
! index used to sign irvec
118+
real(dp) :: ia,ib,ic
119+
120+
! new index used to sign irvec
121+
real(dp) :: new_ia,new_ib,new_ic
122+
integer :: inew_ic
123+
integer :: int_ic
124+
125+
! wave vector k times lattice vector R
126+
real(Dp) :: kdotr
127+
128+
! input wave vector k's cooridinates
129+
real(Dp),intent(in) :: k(2)
130+
131+
! H00 Hamiltonian between nearest neighbour-quintuple-layers
132+
! the factor 2 is induced by spin
133+
134+
complex(dp) :: ratio
135+
136+
complex(Dp), allocatable :: Hij(:, :, :)
137+
138+
! H00 Hamiltonian between nearest neighbour-quintuple-layers
139+
! the factor 2 is induced by spin
140+
141+
! complex(Dp),allocatable,intent(out) :: H00new(:,:)
142+
complex(Dp),intent(out) :: H00new(Ndim,Ndim)
143+
144+
! H01 Hamiltonian between next-nearest neighbour-quintuple-layers
145+
! complex(Dp),allocatable,intent(out) :: H01new(:,:)
146+
complex(Dp),intent(out) :: H01new(Ndim,Ndim)
147+
148+
allocate(Hij(Num_wann,Num_wann,-ijmax:ijmax))
149+
150+
Hij=0.0d0
151+
do iR=1,nrpts_surfacecell
152+
ia=irvec_surfacecell(1,iR)
153+
ib=irvec_surfacecell(2,iR)
154+
ic=irvec_surfacecell(3,iR)
155+
156+
int_ic= int(ic)
157+
if (abs(ic).le.ijmax)then
158+
kdotr=k(1)*ia+ k(2)*ib
159+
ratio=cos(2d0*pi*kdotr)+zi*sin(2d0*pi*kdotr)
160+
161+
Hij(1:Num_wann, 1:Num_wann, int_ic )&
162+
=Hij(1:Num_wann, 1:Num_wann, int_ic)&
163+
+SmnR_surfacecell(:,:,iR)*ratio/ndegen_surfacecell(iR)
164+
endif
165+
166+
enddo
167+
168+
H00new=0.0d0
169+
H01new=0.0d0
170+
171+
! nslab's principle layer
172+
! H00new
173+
do i=1,Np
174+
do j=1,Np
175+
if (abs(i-j).le.(ijmax)) then
176+
H00new(Num_wann*(i-1)+1:Num_wann*i,Num_wann*(j-1)+1:Num_wann*j)&
177+
=Hij(:,:,j-i)
178+
endif
179+
enddo
180+
enddo
181+
182+
! H01new
183+
do i=1,Np
184+
do j=Np+1,Np*2
185+
if (j-i.le.ijmax) then
186+
H01new(Num_wann*(i-1)+1:Num_wann*i,&
187+
Num_wann*(j-1-Np)+1:Num_wann*(j-Np))=Hij(:,:,j-i)
188+
endif
189+
enddo
190+
enddo
191+
192+
do i=1,Ndim
193+
do j=1,Ndim
194+
if(abs(H00new(i,j)-conjg(H00new(j,i))).ge.1e-4)then
195+
! write(stdout,*)'there are something wrong with ham_qlayer2qlayer'
196+
!stop
197+
endif
198+
199+
enddo
200+
enddo
201+
202+
deallocate(Hij)
203+
204+
return
205+
end subroutine s_qlayer2qlayer
206+
207+
104208
subroutine ham_qlayer2qlayer_bak(k,H00new,H01new)
105209
! This subroutine caculates Hamiltonian between
106210
! slabs For surface state calculation
@@ -481,7 +585,55 @@ subroutine ham_qlayer2qlayer2(k,Hij)
481585
return
482586
end subroutine ham_qlayer2qlayer2
483587

588+
subroutine s_qlayer2qlayer2(k,Hij)
589+
! This subroutine caculates Hamiltonian between
590+
! slabs
591+
! 4/23/2010 by QS Wu
592+
! Copyright (c) 2010 QuanSheng Wu. All rights reserved.
593+
594+
use para
595+
596+
implicit none
597+
598+
! loop index
599+
integer :: iR, inew_ic, int_ic
600+
real(dp) :: ia, ib, ic
601+
602+
! new index used to sign irvec
603+
real(dp) :: new_ia,new_ib,new_ic
604+
605+
! wave vector k times lattice vector R
606+
real(Dp) :: kdotr
607+
608+
! input wave vector k's cooridinates
609+
real(Dp),intent(in) :: k(2)
610+
611+
complex(dp) :: ratio
612+
613+
complex(Dp), intent(out) :: Hij(-ijmax:ijmax,Num_wann,Num_wann)
614+
615+
Hij=0.0d0
616+
617+
do iR=1,nrpts_surfacecell
618+
ia=irvec_surfacecell(1,iR)
619+
ib=irvec_surfacecell(2,iR)
620+
ic=irvec_surfacecell(3,iR)
621+
622+
int_ic= int(ic)
623+
if (abs(ic).le.ijmax)then
624+
kdotr=k(1)*ia+k(2)*ib
625+
ratio=cos(2d0*pi*kdotr)+zi*sin(2d0*pi*kdotr)
626+
627+
Hij(int_ic, 1:Num_wann, 1:Num_wann )&
628+
=Hij(int_ic, 1:Num_wann, 1:Num_wann )&
629+
+SmnR_surfacecell(:,:,iR)*ratio/ndegen_surfacecell(iR)
630+
631+
endif
632+
633+
enddo
484634

635+
return
636+
end subroutine s_qlayer2qlayer2
485637

486638
subroutine ham_qlayer2qlayer2_LOTO(k,Hij)
487639
! This subroutine caculates Hamiltonian between

0 commit comments

Comments
 (0)