mirror of https://gitlab.com/QEF/q-e.git
290 lines
9.2 KiB
Fortran
290 lines
9.2 KiB
Fortran
!
|
|
! Copyright (C) 2001 PWSCF group
|
|
! This file is distributed under the terms of the
|
|
! GNU General Public License. See the file `License'
|
|
! in the root directory of the present distribution,
|
|
! or http://www.gnu.org/copyleft/gpl.txt .
|
|
!
|
|
!-----------------------------------------------------------------------
|
|
subroutine kpoint_grid &
|
|
( nrot, s, bg, npk, k1,k2,k3, nk1,nk2,nk3, nks, xk, wk)
|
|
!-----------------------------------------------------------------------
|
|
!
|
|
! Automatic generation of a uniform grid of k-points
|
|
!
|
|
#include "machine.h"
|
|
use parameters, only: DP
|
|
implicit none
|
|
! INPUT:
|
|
integer nrot, s(3,3,48), npk, k1, k2, k3, nk1, nk2, nk3
|
|
real(kind=DP) bg(3,3)
|
|
! OUTPUT:
|
|
integer nks
|
|
real(kind=DP) xk(3,npk), wk(npk)
|
|
! LOCAL:
|
|
real(kind=DP), parameter :: degspin=2.d0, eps=1.0e-5
|
|
! degspin: spin degeneracy used to normalize k-points
|
|
real(kind=DP) xkr(3), deltap(3), deltam(3), fact
|
|
real(kind=DP), allocatable:: xkg(:,:)
|
|
integer nkr, i,j,k, ns, n, nk
|
|
integer, allocatable :: equiv(:)
|
|
!
|
|
nkr=nk1*nk2*nk3
|
|
allocate (xkg( 3,nkr))
|
|
allocate (equiv( nkr))
|
|
!
|
|
do i=1,nk1
|
|
do j=1,nk2
|
|
do k=1,nk3
|
|
! this is nothing but consecutive ordering
|
|
n = (k-1) + (j-1)*nk3 + (i-1)*nk2*nk3 + 1
|
|
! xkg are the components of the complete grid in crystal axis
|
|
xkg(1,n) = dble(i-1)/nk1 + dble(k1)/2/nk1
|
|
xkg(2,n) = dble(j-1)/nk2 + dble(k2)/2/nk2
|
|
xkg(3,n) = dble(k-1)/nk3 + dble(k3)/2/nk3
|
|
end do
|
|
end do
|
|
end do
|
|
|
|
! equiv(nk) =nk : k-point nk is not equivalent to any previous k-point
|
|
! equiv(nk)!=nk : k-point nk is equivalent to k-point equiv(nk)
|
|
|
|
do nk=1,nkr
|
|
equiv(nk)=nk
|
|
end do
|
|
|
|
do nk=1,nkr
|
|
! check if this k-point has already been found equivalent to another
|
|
if (equiv(nk).eq.nk) then
|
|
wk(nk) = 1.0
|
|
do n=nk+1,nkr
|
|
! check if there are equivalent k-point to this in the list
|
|
! (excepted those previously found to be equivalent to another)
|
|
if (equiv(n).eq.n) then
|
|
do ns=1,nrot
|
|
do i=1,3
|
|
xkr(i) = s(i,1,ns) * xkg(1,n) &
|
|
+ s(i,2,ns) * xkg(2,n) &
|
|
+ s(i,3,ns) * xkg(3,n)
|
|
end do
|
|
! xkr are the components in crystal axis of the rotated k-point
|
|
do i=1,3
|
|
deltap(i) = xkr(i)-xkg(i,nk) - &
|
|
nint (xkr(i)-xkg(i,nk) )
|
|
deltam(i) = xkr(i)+xkg(i,nk) - &
|
|
nint (xkr(i)+xkg(i,nk) )
|
|
end do
|
|
! deltap is the difference vector,
|
|
! brought back in the first BZ
|
|
! deltam is the same but with k => -k (for time reversal)
|
|
if ( sqrt ( deltap(1)**2 + &
|
|
deltap(2)**2 + &
|
|
deltap(3)**2 ) .lt. eps .or. &
|
|
sqrt ( deltam(1)**2 + &
|
|
deltam(2)**2 + &
|
|
deltam(3)**2 ) .lt. eps ) then
|
|
! equivalent k-point found:
|
|
! add 1 to the weight and go to next k-point
|
|
equiv(n) = nk
|
|
wk(nk)=wk(nk)+1.0
|
|
go to 10
|
|
end if
|
|
end do
|
|
end if
|
|
10 continue
|
|
end do
|
|
end if
|
|
end do
|
|
|
|
! count irreducible points and order them
|
|
|
|
nks=0
|
|
fact=0.0
|
|
do nk=1,nkr
|
|
if (equiv(nk).eq.nk) then
|
|
nks=nks+1
|
|
if (nks.gt.npk) call error('kpoint_grid','too many k-points',1)
|
|
wk(nks) = wk(nk)
|
|
fact = fact+wk(nks)
|
|
! bring back into to the first BZ
|
|
do i=1,3
|
|
xk(i,nks) = xkg(i,nk)-nint(xkg(i,nk))
|
|
end do
|
|
end if
|
|
end do
|
|
! go to cartesian axis (in units 2pi/a0)
|
|
call cryst_to_cart(nks,xk,bg,1)
|
|
! normalize weights to degspin (every band can accomodate 2 electrons)
|
|
do nk=1,nks
|
|
wk(nk) = degspin * wk(nk)/fact
|
|
end do
|
|
|
|
deallocate(equiv)
|
|
deallocate(xkg)
|
|
|
|
return
|
|
end subroutine kpoint_grid
|
|
!
|
|
!-----------------------------------------------------------------------
|
|
subroutine tetrahedra ( nsym, s, minus_q, at, bg, npk, k1,k2,k3, &
|
|
nk1,nk2,nk3, nks, xk, wk, ntetra, tetra )
|
|
!-----------------------------------------------------------------------
|
|
!
|
|
! Tetrahedron method according to P. E. Bloechl et al, PRB49, 16223 (1994)
|
|
!
|
|
#include "machine.h"
|
|
use parameters, only: DP
|
|
implicit none
|
|
! INPUT:
|
|
integer nks, nsym, s(3,3,48), npk, k1, k2, k3, nk1, nk2, nk3, ntetra
|
|
logical minus_q
|
|
real(kind=DP) :: at(3,3), bg(3,3), xk(3,npk), wk(npk)
|
|
! OUTPUT:
|
|
integer tetra(4,ntetra)
|
|
! LOCAL:
|
|
real(kind=DP) :: xkr(3), deltap(3), deltam(3)
|
|
real(kind=DP), parameter:: eps=1.0d-5
|
|
real(kind=DP), allocatable :: xkg(:,:)
|
|
integer :: nkr, i,j,k, ns, n, nk, ip1,jp1,kp1, &
|
|
n1,n2,n3,n4,n5,n6,n7,n8
|
|
integer, allocatable:: equiv(:)
|
|
!
|
|
! Re-generate a uniform grid of k-points xkg
|
|
!
|
|
nkr=nk1*nk2*nk3
|
|
! ntetra=6*nkr
|
|
allocate (xkg( 3,nkr))
|
|
allocate (equiv( nkr))
|
|
!
|
|
do i=1,nk1
|
|
do j=1,nk2
|
|
do k=1,nk3
|
|
! this is nothing but consecutive ordering
|
|
n = (k-1) + (j-1)*nk3 + (i-1)*nk2*nk3 + 1
|
|
! xkg are the components of the complete grid in crystal axis
|
|
xkg(1,n) = dble(i-1)/nk1 + dble(k1)/2/nk1
|
|
xkg(2,n) = dble(j-1)/nk2 + dble(k2)/2/nk2
|
|
xkg(3,n) = dble(k-1)/nk3 + dble(k3)/2/nk3
|
|
end do
|
|
end do
|
|
end do
|
|
|
|
! locate k-points of the uniform grid in the list of irreducible k-points
|
|
! that was previously calculated
|
|
|
|
! bring irreducible k-points to crystal axis
|
|
call cryst_to_cart (nks,xk,at,-1)
|
|
!
|
|
do nk=1,nkr
|
|
do n=1,nks
|
|
do ns=1,nsym
|
|
do i=1,3
|
|
xkr(i) = s(i,1,ns) * xk(1,n) + &
|
|
s(i,2,ns) * xk(2,n) + &
|
|
s(i,3,ns) * xk(3,n)
|
|
end do
|
|
! xkr is the n-th irreducible k-point rotated wrt the ns-th symmetry
|
|
do i=1,3
|
|
deltap(i) = xkr(i)-xkg(i,nk) - nint (xkr(i)-xkg(i,nk) )
|
|
deltam(i) = xkr(i)+xkg(i,nk) - nint (xkr(i)+xkg(i,nk) )
|
|
end do
|
|
! deltap is the difference vector, brought back in the first BZ
|
|
! deltam is the same but with k => -k (for time reversal)
|
|
if ( sqrt ( deltap(1)**2 + &
|
|
deltap(2)**2 + &
|
|
deltap(3)**2 ) .lt. eps .or. ( minus_q .and. &
|
|
sqrt ( deltam(1)**2 + &
|
|
deltam(2)**2 + &
|
|
deltam(3)**2 ) .lt. eps ) ) then
|
|
! equivalent irreducible k-point found
|
|
equiv(nk) = n
|
|
go to 15
|
|
end if
|
|
end do
|
|
end do
|
|
! equivalent irreducible k-point found - something wrong
|
|
call error('tetrahedra','cannot locate k point',nk)
|
|
15 continue
|
|
end do
|
|
|
|
do n=1,nks
|
|
do nk=1,nkr
|
|
if (equiv(nk).eq.n) go to 20
|
|
end do
|
|
! this failure of the algorithm may indicate that the displaced grid
|
|
! (with k1,k2,k3.ne.0) does not have the full symmetry of the lattice
|
|
call error('tetrahedra','cannot remap grid on k-point list',n)
|
|
20 continue
|
|
end do
|
|
|
|
! bring irreducible k-points back to cartesian axis
|
|
call cryst_to_cart (nks,xk,bg, 1)
|
|
|
|
! construct tetrahedra
|
|
|
|
do i=1,nk1
|
|
do j=1,nk2
|
|
do k=1,nk3
|
|
! n1-n8 are the indices of k-point 1-8 forming a cube
|
|
ip1 = mod(i,nk1)+1
|
|
jp1 = mod(j,nk2)+1
|
|
kp1 = mod(k,nk3)+1
|
|
n1 = ( k-1) + ( j-1)*nk3 + ( i-1)*nk2*nk3 + 1
|
|
n2 = ( k-1) + ( j-1)*nk3 + (ip1-1)*nk2*nk3 + 1
|
|
n3 = ( k-1) + (jp1-1)*nk3 + ( i-1)*nk2*nk3 + 1
|
|
n4 = ( k-1) + (jp1-1)*nk3 + (ip1-1)*nk2*nk3 + 1
|
|
n5 = (kp1-1) + ( j-1)*nk3 + ( i-1)*nk2*nk3 + 1
|
|
n6 = (kp1-1) + ( j-1)*nk3 + (ip1-1)*nk2*nk3 + 1
|
|
n7 = (kp1-1) + (jp1-1)*nk3 + ( i-1)*nk2*nk3 + 1
|
|
n8 = (kp1-1) + (jp1-1)*nk3 + (ip1-1)*nk2*nk3 + 1
|
|
! there are 6 tetrahedra per cube (and nk1*nk2*nk3 cubes)
|
|
n = 6 * ( (k-1) + (j-1)*nk3 + (i-1)*nk3*nk2 )
|
|
|
|
tetra (1,n+1) = equiv(n1)
|
|
tetra (2,n+1) = equiv(n2)
|
|
tetra (3,n+1) = equiv(n3)
|
|
tetra (4,n+1) = equiv(n6)
|
|
|
|
tetra (1,n+2) = equiv(n2)
|
|
tetra (2,n+2) = equiv(n3)
|
|
tetra (3,n+2) = equiv(n4)
|
|
tetra (4,n+2) = equiv(n6)
|
|
|
|
tetra (1,n+3) = equiv(n1)
|
|
tetra (2,n+3) = equiv(n3)
|
|
tetra (3,n+3) = equiv(n5)
|
|
tetra (4,n+3) = equiv(n6)
|
|
|
|
tetra (1,n+4) = equiv(n3)
|
|
tetra (2,n+4) = equiv(n4)
|
|
tetra (3,n+4) = equiv(n6)
|
|
tetra (4,n+4) = equiv(n8)
|
|
|
|
tetra (1,n+5) = equiv(n3)
|
|
tetra (2,n+5) = equiv(n6)
|
|
tetra (3,n+5) = equiv(n7)
|
|
tetra (4,n+5) = equiv(n8)
|
|
|
|
tetra (1,n+6) = equiv(n3)
|
|
tetra (2,n+6) = equiv(n5)
|
|
tetra (3,n+6) = equiv(n6)
|
|
tetra (4,n+6) = equiv(n7)
|
|
end do
|
|
end do
|
|
end do
|
|
|
|
! check
|
|
|
|
do n=1,ntetra
|
|
do i=1,4
|
|
if ( tetra(i,n).lt.1 .or. tetra(i,n).gt.nks ) &
|
|
call error ('tetrahedra','something wrong',n)
|
|
end do
|
|
end do
|
|
|
|
deallocate(equiv)
|
|
deallocate(xkg)
|
|
|
|
return
|
|
end subroutine tetrahedra
|