mirror of https://gitlab.com/QEF/q-e.git
820 lines
27 KiB
Fortran
820 lines
27 KiB
Fortran
!
|
|
! Copyright (C) 2002 FPMD 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 .
|
|
!
|
|
|
|
!=----------------------------------------------------------------------=
|
|
MODULE stick_base
|
|
!=----------------------------------------------------------------------=
|
|
|
|
USE kinds
|
|
USE io_global, ONLY: ionode
|
|
|
|
IMPLICIT NONE
|
|
PRIVATE
|
|
SAVE
|
|
|
|
PUBLIC :: sticks_maps, sticks_sort, sticks_countg, sticks_dist, sticks_pairup
|
|
PUBLIC :: sticks_owner, sticks_deallocate, pstickset, sticks_maps_scalar
|
|
|
|
! ... sticks_owner : stick owner, sticks_owner( i, j ) is the index of the processor
|
|
! ... (starting from 1) owning the stick whose x and y coordinate are i and j.
|
|
|
|
INTEGER, ALLOCATABLE, TARGET :: sticks_owner( : , : )
|
|
|
|
INTERFACE sticks_dist
|
|
MODULE PROCEDURE sticks_dist1
|
|
END INTERFACE
|
|
|
|
!=----------------------------------------------------------------------=
|
|
CONTAINS
|
|
!=----------------------------------------------------------------------=
|
|
|
|
SUBROUTINE sticks_maps( tk, ub, lb, b1, b2, b3, gcut, gcutw, gcuts, st, stw, sts )
|
|
|
|
USE mp, ONLY: mp_sum
|
|
USE mp_global, ONLY: me_pool, nproc_pool, intra_pool_comm, my_image_id
|
|
|
|
LOGICAL, INTENT(IN) :: tk ! if true use the full space grid
|
|
INTEGER, INTENT(IN) :: ub(:) ! upper bounds for i-th grid dimension
|
|
INTEGER, INTENT(IN) :: lb(:) ! lower bounds for i-th grid dimension
|
|
REAL(dbl) , INTENT(IN) :: b1(:), b2(:), b3(:) ! reciprocal space base vectors
|
|
REAL(dbl) , INTENT(IN) :: gcut ! cut-off for potentials
|
|
REAL(dbl) , INTENT(IN) :: gcutw ! cut-off for plane waves
|
|
REAL(dbl) , INTENT(IN) :: gcuts ! cut-off for smooth mesh
|
|
INTEGER, INTENT(OUT) :: st( lb(1): ub(1), lb(2):ub(2) ) ! stick map for potential
|
|
INTEGER, INTENT(OUT) :: stw(lb(1): ub(1), lb(2):ub(2) ) ! stick map for wave functions
|
|
INTEGER, INTENT(OUT) :: sts(lb(1): ub(1), lb(2):ub(2) ) ! stick map for smooth mesh
|
|
|
|
INTEGER :: i, j, k, kip
|
|
REAL(dbl) :: gsq
|
|
|
|
stw = 0
|
|
st = 0
|
|
sts = 0
|
|
|
|
! ... Here find the basic maps of sticks st, stw and sts for the potential
|
|
! ... cut-off gcut, wavefunction cut-off gcutw, and smooth mesh cut-off gcuts
|
|
|
|
! ... st(i,j) will contain the number of G vectors of the stick whose
|
|
! ... indices are (i,j).
|
|
|
|
IF( .NOT. tk ) THEN
|
|
|
|
kip = 0 + ABS(lb(3)) + 1
|
|
IF( MOD( kip, nproc_pool ) == me_pool ) THEN
|
|
st (0,0) = st (0,0) + 1
|
|
stw(0,0) = stw(0,0) + 1
|
|
sts(0,0) = sts(0,0) + 1
|
|
END IF
|
|
|
|
DO i= 0, 0
|
|
DO j= 0, 0
|
|
DO k= 1, ub(3)
|
|
kip = k + ABS(lb(3)) + 1
|
|
IF( MOD( kip, nproc_pool ) == me_pool ) THEN
|
|
gsq= (REAL(i)*b1(1)+REAL(j)*b2(1)+REAL(k)*b3(1) )**2
|
|
gsq=gsq+(REAL(i)*b1(2)+REAL(j)*b2(2)+REAL(k)*b3(2) )**2
|
|
gsq=gsq+(REAL(i)*b1(3)+REAL(j)*b2(3)+REAL(k)*b3(3) )**2
|
|
IF(gsq.LE.gcut ) THEN
|
|
st(i,j) = st(i,j) + 1
|
|
IF(gsq.LE.gcutw) THEN
|
|
stw(i,j) = stw(i,j) + 1
|
|
END IF
|
|
IF(gsq.LE.gcuts) THEN
|
|
sts(i,j) = sts(i,j) + 1
|
|
END IF
|
|
END IF
|
|
END IF
|
|
END DO
|
|
END DO
|
|
END DO
|
|
|
|
DO i = 0, 0
|
|
DO j = 1, ub(2)
|
|
DO k = lb(3), ub(3)
|
|
kip = k + ABS(lb(3)) + 1
|
|
IF( MOD( kip, nproc_pool) == me_pool ) THEN
|
|
gsq= (REAL(i)*b1(1)+REAL(j)*b2(1)+REAL(k)*b3(1) )**2
|
|
gsq=gsq+(REAL(i)*b1(2)+REAL(j)*b2(2)+REAL(k)*b3(2) )**2
|
|
gsq=gsq+(REAL(i)*b1(3)+REAL(j)*b2(3)+REAL(k)*b3(3) )**2
|
|
IF(gsq.LE.gcut ) THEN
|
|
st(i,j) = st(i,j) + 1
|
|
IF(gsq.LE.gcutw) THEN
|
|
stw(i,j) = stw(i,j) + 1
|
|
END IF
|
|
IF(gsq.LE.gcuts) THEN
|
|
sts(i,j) = sts(i,j) + 1
|
|
END IF
|
|
END IF
|
|
END IF
|
|
END DO
|
|
END DO
|
|
END DO
|
|
|
|
DO i = 1, ub(1)
|
|
DO j = lb(2), ub(2)
|
|
DO k = lb(3), ub(3)
|
|
kip = k + ABS(lb(3)) + 1
|
|
IF( MOD( kip, nproc_pool) == me_pool ) THEN
|
|
gsq= (REAL(i)*b1(1)+REAL(j)*b2(1)+REAL(k)*b3(1) )**2
|
|
gsq=gsq+(REAL(i)*b1(2)+REAL(j)*b2(2)+REAL(k)*b3(2) )**2
|
|
gsq=gsq+(REAL(i)*b1(3)+REAL(j)*b2(3)+REAL(k)*b3(3) )**2
|
|
IF(gsq.LE.gcut ) THEN
|
|
st(i,j) = st(i,j) + 1
|
|
IF(gsq.LE.gcutw) THEN
|
|
stw(i,j) = stw(i,j) + 1
|
|
END IF
|
|
IF(gsq.LE.gcuts) THEN
|
|
sts(i,j) = sts(i,j) + 1
|
|
END IF
|
|
END IF
|
|
END IF
|
|
END DO
|
|
END DO
|
|
END DO
|
|
|
|
ELSE
|
|
|
|
DO i= lb(1), ub(1)
|
|
DO j= lb(2), ub(2)
|
|
DO k= lb(3), ub(3)
|
|
kip = k + ABS(lb(3)) + 1
|
|
IF( MOD( kip, nproc_pool ) == me_pool ) THEN
|
|
gsq= (REAL(i)*b1(1)+REAL(j)*b2(1)+REAL(k)*b3(1) )**2
|
|
gsq=gsq+(REAL(i)*b1(2)+REAL(j)*b2(2)+REAL(k)*b3(2) )**2
|
|
gsq=gsq+(REAL(i)*b1(3)+REAL(j)*b2(3)+REAL(k)*b3(3) )**2
|
|
IF(gsq.LE.gcut ) THEN
|
|
st(i,j) = st(i,j) + 1
|
|
END IF
|
|
IF(gsq.LE.gcutw) THEN
|
|
stw(i,j) = stw(i,j) + 1
|
|
END IF
|
|
IF(gsq.LE.gcuts) THEN
|
|
sts(i,j) = sts(i,j) + 1
|
|
END IF
|
|
END IF
|
|
END DO
|
|
END DO
|
|
END DO
|
|
|
|
END IF
|
|
|
|
CALL mp_sum(st ,intra_pool_comm )
|
|
CALL mp_sum(stw ,intra_pool_comm )
|
|
CALL mp_sum(sts ,intra_pool_comm )
|
|
|
|
! Test sticks
|
|
! WRITE( 6,*) 'testtesttesttesttesttesttesttesttesttest'
|
|
! WRITE( 6,*) 'lb = ', lb(1), lb(2)
|
|
! WRITE( 6,*) 'ub = ', ub(1), ub(2)
|
|
! WRITE( 6,*) 'counts = ', COUNT( st > 0 ), COUNT( stw > 0 ), COUNT( sts > 0 )
|
|
! WRITE( 6,*) 'cut-offs = ', gcut, gcutw, gcuts
|
|
! WRITE( 6,*) 'b1 = ', b1(1:3)
|
|
! WRITE( 6,*) 'b2 = ', b2(1:3)
|
|
! WRITE( 6,*) 'b3 = ', b3(1:3)
|
|
! DO i = lb(1), ub(1)
|
|
! DO j = lb(2), ub(2)
|
|
! WRITE( 6,'(2I4,I6)') i,j,stw(i,j)
|
|
! END DO
|
|
! END DO
|
|
! WRITE( 6,*) 'testtesttesttesttesttesttesttesttesttest'
|
|
! Test sticks
|
|
|
|
RETURN
|
|
END SUBROUTINE
|
|
|
|
!=----------------------------------------------------------------------=
|
|
|
|
SUBROUTINE sticks_maps_scalar( lgamma, ub, lb, b1, b2, b3, gcutm, gkcut, gcutms, stw, ngm, ngms )
|
|
|
|
LOGICAL, INTENT(IN) :: lgamma ! if true use gamma point simmetry
|
|
INTEGER, INTENT(IN) :: ub(:) ! upper bounds for i-th grid dimension
|
|
INTEGER, INTENT(IN) :: lb(:) ! lower bounds for i-th grid dimension
|
|
REAL(dbl) , INTENT(IN) :: b1(:), b2(:), b3(:) ! reciprocal space base vectors
|
|
REAL(dbl) , INTENT(IN) :: gcutm ! cut-off for potentials
|
|
REAL(dbl) , INTENT(IN) :: gkcut ! cut-off for plane waves
|
|
REAL(dbl) , INTENT(IN) :: gcutms ! cut-off for smooth mesh
|
|
!
|
|
INTEGER, INTENT(OUT) :: ngm, ngms
|
|
!
|
|
! stick map for wave functions, note that map is taken in YZ plane
|
|
!
|
|
INTEGER, INTENT(OUT) :: stw( lb(2) : ub(2), lb(3) : ub(3) )
|
|
|
|
INTEGER :: i1, i2, i3, n1, n2, n3
|
|
REAL(dbl) :: amod
|
|
|
|
ngm = 0
|
|
ngms = 0
|
|
|
|
n1 = MAX( ABS( lb(1) ), ABS( ub(1) ) )
|
|
n2 = MAX( ABS( lb(2) ), ABS( ub(2) ) )
|
|
n3 = MAX( ABS( lb(3) ), ABS( ub(3) ) )
|
|
|
|
loop1: do i1 = - n1, n1
|
|
!
|
|
! Gamma-only: exclude space with x<0
|
|
!
|
|
if (lgamma .and. i1 < 0) cycle loop1
|
|
!
|
|
loop2: do i2 = - n2, n2
|
|
!
|
|
! Gamma-only: exclude plane with x=0, y<0
|
|
!
|
|
if(lgamma .and. i1 == 0.and. i2 < 0) cycle loop2
|
|
!
|
|
loop3: do i3 = - n3, n3
|
|
!
|
|
! Gamma-only: exclude line with x=0, y=0, z<0
|
|
!
|
|
if(lgamma .and. i1 == 0 .and. i2 == 0 .and. i3 < 0) cycle loop3
|
|
!
|
|
amod = (i1 * b1 (1) + i2 * b2 (1) + i3 * b3 (1) ) **2 + &
|
|
(i1 * b1 (2) + i2 * b2 (2) + i3 * b3 (2) ) **2 + &
|
|
(i1 * b1 (3) + i2 * b2 (3) + i3 * b3 (3) ) **2
|
|
if (amod <= gcutm) ngm = ngm + 1
|
|
if (amod <= gcutms) ngms = ngms + 1
|
|
if (amod <= gkcut ) then
|
|
stw( i2, i3 ) = 1
|
|
if (lgamma) stw( -i2, -i3 ) = 1
|
|
end if
|
|
enddo loop3
|
|
enddo loop2
|
|
enddo loop1
|
|
|
|
RETURN
|
|
END SUBROUTINE
|
|
|
|
|
|
!=----------------------------------------------------------------------=
|
|
|
|
SUBROUTINE sticks_sort( ngc, ngcw, ngcs, nct, index )
|
|
|
|
! ... This subroutine sorts the sticks indexes, according to
|
|
! ... the lenght and type of the sticks, wave functions sticks
|
|
! ... first, then smooth mesh sticks, and finally potential
|
|
! ... sticks
|
|
|
|
USE mp_global, ONLY: nproc_pool
|
|
|
|
! lenghts of sticks, ngc for potential mesh, ngcw for wave functions mesh
|
|
! and ngcs for smooth mesh
|
|
|
|
INTEGER, INTENT(IN) :: ngc(:), ngcw(:), ngcs(:)
|
|
|
|
! nct, total number of sticks
|
|
|
|
INTEGER, INTENT(IN) :: nct
|
|
|
|
! index, on output, new sticks indexes
|
|
|
|
INTEGER, INTENT(OUT) :: index(:)
|
|
|
|
INTEGER :: mc, nr3x, ic
|
|
REAL(dbl), ALLOCATABLE :: aux(:)
|
|
|
|
nr3x = MAXVAL( ngc(1:nct) ) + 1
|
|
|
|
IF( nproc_pool > 1 ) THEN
|
|
ALLOCATE( aux( nct ) )
|
|
DO mc = 1, nct
|
|
aux(mc) = -(ngcw(mc)*nr3x**2 + ngcs(mc)*nr3x + ngc(mc))
|
|
index(mc) = 0
|
|
END DO
|
|
CALL hpsort( nct, aux(1), index(1))
|
|
DEALLOCATE( aux )
|
|
ELSE
|
|
ic = 0
|
|
do mc = 1, nct
|
|
if( ngcw(mc) > 0 ) then
|
|
ic = ic + 1
|
|
index(ic) = mc
|
|
endif
|
|
end do
|
|
do mc = 1, nct
|
|
if( ngcs(mc) > 0 .AND. ngcw(mc) == 0 ) then
|
|
ic = ic + 1
|
|
index(ic) = mc
|
|
endif
|
|
end do
|
|
do mc = 1, nct
|
|
if( ngc(mc) > 0 .AND. ngcs(mc) == 0 .AND. ngcw(mc) == 0 ) then
|
|
ic = ic + 1
|
|
index(ic) = mc
|
|
endif
|
|
end do
|
|
END IF
|
|
|
|
! WRITE( stdout,*) '-----------------'
|
|
! WRITE( stdout,*) 'STICKS_SORT DEBUG'
|
|
! DO mc = 1, nct
|
|
! WRITE( stdout, fmt="(4I10)" ) index(mc), ngcw( index(mc) ), ngcs( index(mc) ), ngc( index(mc) )
|
|
! END DO
|
|
! WRITE( stdout,*) '-----------------'
|
|
|
|
RETURN
|
|
END SUBROUTINE
|
|
|
|
!=----------------------------------------------------------------------=
|
|
|
|
SUBROUTINE sticks_countg( tk, ub, lb, st, stw, sts, in1, in2, ngc, ngcw, ngcs )
|
|
|
|
INTEGER, INTENT(IN) :: ub(:), lb(:)
|
|
INTEGER, INTENT(IN) :: st( lb(1): ub(1), lb(2):ub(2) ) ! stick map for potential
|
|
INTEGER, INTENT(IN) :: stw(lb(1): ub(1), lb(2):ub(2) ) ! stick map for wave functions
|
|
INTEGER, INTENT(IN) :: sts(lb(1): ub(1), lb(2):ub(2) ) ! stick map for smooth mesh
|
|
LOGICAL, INTENT(IN) :: tk
|
|
|
|
INTEGER, INTENT(OUT) :: in1(:), in2(:)
|
|
INTEGER, INTENT(OUT) :: ngc(:), ngcw(:), ngcs(:)
|
|
|
|
INTEGER :: j1, j2, i1, i2, nct, min_size
|
|
|
|
!
|
|
! ... initialize the sticks indexes array ist
|
|
! ... nct counts columns containing G-vectors for the dense grid
|
|
! ... ncts counts columns contaning G-vectors for the smooth grid
|
|
!
|
|
nct = 0
|
|
|
|
ngc = 0
|
|
ngcs = 0
|
|
ngcw = 0
|
|
|
|
min_size = MIN( SIZE( in1 ), SIZE( in2 ), SIZE( ngc ), SIZE( ngcw ), SIZE( ngcs ) )
|
|
|
|
DO j2 = 0, ( ub(2) - lb(2) )
|
|
DO j1 = 0, ( ub(1) - lb(1) )
|
|
|
|
i1 = j1
|
|
if( i1 > ub(1) ) i1 = lb(1) + ( i1 - ub(1) ) - 1
|
|
|
|
i2 = j2
|
|
if( i2 > ub(2) ) i2 = lb(2) + ( i2 - ub(2) ) - 1
|
|
|
|
IF( st( i1, i2 ) > 0 ) THEN
|
|
|
|
! this sticks contains G-vectors
|
|
|
|
nct = nct + 1
|
|
IF( nct > min_size ) &
|
|
CALL errore(' sticks_countg ',' too many sticks ', nct )
|
|
|
|
in1(nct) = i1
|
|
in2(nct) = i2
|
|
|
|
ngc(nct) = st( i1 , i2)
|
|
IF( stw( i1, i2 ) .GT. 0 ) ngcw(nct) = stw( i1 , i2)
|
|
IF( sts( i1, i2 ) .GT. 0 ) ngcs(nct) = sts( i1 , i2)
|
|
|
|
END IF
|
|
|
|
! WRITE(7,fmt="(5I5)") i1, i2, nct, ngc(nct), ngcw( nct )
|
|
|
|
END DO
|
|
END DO
|
|
|
|
RETURN
|
|
END SUBROUTINE
|
|
|
|
!=----------------------------------------------------------------------=
|
|
|
|
SUBROUTINE sticks_dist1( tk, ub, lb, index, in1, in2, ngc, ngcw, ngcs, nct, &
|
|
ncp, ncpw, ncps, ngp, ngpw, ngps, stown, stownw, stowns )
|
|
|
|
USE mp_global, ONLY: nproc_pool
|
|
|
|
LOGICAL, INTENT(IN) :: tk
|
|
|
|
INTEGER, INTENT(IN) :: ub(:), lb(:), index(:)
|
|
INTEGER, INTENT(OUT) :: stown( lb(1): ub(1), lb(2):ub(2) ) ! stick map for potential
|
|
INTEGER, INTENT(OUT) :: stownw(lb(1): ub(1), lb(2):ub(2) ) ! stick map for wave functions
|
|
INTEGER, INTENT(OUT) :: stowns(lb(1): ub(1), lb(2):ub(2) ) ! stick map for smooth mesh
|
|
|
|
INTEGER, INTENT(IN) :: in1(:), in2(:)
|
|
INTEGER, INTENT(IN) :: ngc(:), ngcw(:), ngcs(:)
|
|
INTEGER, INTENT(IN) :: nct
|
|
INTEGER, INTENT(OUT) :: ncp(:), ncpw(:), ncps(:)
|
|
INTEGER, INTENT(OUT) :: ngp(:), ngpw(:), ngps(:)
|
|
|
|
INTEGER :: mc, i1, i2, i, j, jj
|
|
|
|
ncp = 0
|
|
ncps = 0
|
|
ncpw = 0
|
|
ngp = 0
|
|
ngps = 0
|
|
ngpw = 0
|
|
|
|
stown = 0
|
|
stownw = 0
|
|
stowns = 0
|
|
|
|
DO mc = 1, nct
|
|
|
|
i = index( mc )
|
|
!
|
|
! index contains the desired ordering of sticks (see above)
|
|
!
|
|
i1 = in1( i )
|
|
i2 = in2( i )
|
|
!
|
|
if ( ( .NOT. tk ) .AND. ( (i1 < 0) .or. ( (i1 == 0) .and. (i2 < 0) ) ) ) go to 30
|
|
!
|
|
jj = 1
|
|
|
|
if ( ngcw(i) > 0 ) then
|
|
!
|
|
! this is an active sticks: find which processor has currently
|
|
! the smallest number of plane waves
|
|
!
|
|
do j = 1, nproc_pool
|
|
if ( ngpw(j) < ngpw(jj) ) then
|
|
jj = j
|
|
else if ( ( ngpw(j) == ngpw(jj) ) .AND. ( ncpw(j) < ncpw(jj) ) ) then
|
|
jj = j
|
|
end if
|
|
end do
|
|
|
|
else
|
|
!
|
|
! this is an inactive sticks: find which processor has currently
|
|
! the smallest number of G-vectors
|
|
!
|
|
do j = 1, nproc_pool
|
|
if ( ngp(j) < ngp(jj) ) jj = j
|
|
end do
|
|
|
|
end if
|
|
!
|
|
! potential mesh
|
|
|
|
ncp(jj) = ncp(jj) + 1
|
|
ngp(jj) = ngp(jj) + ngc(i)
|
|
stown(i1,i2) = jj
|
|
|
|
! smooth mesh
|
|
|
|
if ( ngcs(i) > 0 ) then
|
|
ncps(jj) = ncps(jj) + 1
|
|
ngps(jj) = ngps(jj) + ngcs(i)
|
|
stowns(i1,i2) = jj
|
|
endif
|
|
|
|
! wave functions mesh
|
|
|
|
if ( ngcw(i) > 0 ) then
|
|
ncpw(jj) = ncpw(jj) + 1
|
|
ngpw(jj) = ngpw(jj) + ngcw(i)
|
|
stownw(i1,i2) = jj
|
|
endif
|
|
|
|
30 continue
|
|
|
|
END DO
|
|
|
|
RETURN
|
|
END SUBROUTINE
|
|
|
|
!=----------------------------------------------------------------------=
|
|
|
|
SUBROUTINE sticks_pairup( tk, ub, lb, index, in1, in2, ngc, ngcw, ngcs, nct, &
|
|
ncp, ncpw, ncps, ngp, ngpw, ngps, stown, stownw, stowns )
|
|
|
|
USE mp_global, ONLY: nproc_pool
|
|
|
|
LOGICAL, INTENT(IN) :: tk
|
|
|
|
INTEGER, INTENT(IN) :: ub(:), lb(:), index(:)
|
|
INTEGER, INTENT(INOUT) :: stown( lb(1): ub(1), lb(2):ub(2) ) ! stick map for potential
|
|
INTEGER, INTENT(INOUT) :: stownw(lb(1): ub(1), lb(2):ub(2) ) ! stick map for wave functions
|
|
INTEGER, INTENT(INOUT) :: stowns(lb(1): ub(1), lb(2):ub(2) ) ! stick map for wave functions
|
|
|
|
INTEGER, INTENT(IN) :: in1(:), in2(:)
|
|
INTEGER, INTENT(IN) :: ngc(:), ngcw(:), ngcs(:)
|
|
INTEGER, INTENT(IN) :: nct
|
|
INTEGER, INTENT(OUT) :: ncp(:), ncpw(:), ncps(:)
|
|
INTEGER, INTENT(OUT) :: ngp(:), ngpw(:), ngps(:)
|
|
|
|
INTEGER :: mc, i1, i2, i, j, jj, iss, is, ip
|
|
|
|
IF ( .NOT. tk ) THEN
|
|
|
|
! when gamma symmetry is used only the sticks of half reciprocal space
|
|
! are generated, then here we pair-up the sticks with those of the other
|
|
! half of the space, using the gamma symmetry relation
|
|
! Note that the total numero of stick "nct" is not modified
|
|
|
|
DO mc = 1, nct
|
|
i = index(mc)
|
|
i1 = in1(i)
|
|
i2 = in2(i)
|
|
IF( i1 == 0 .and. i2 == 0 ) THEN
|
|
jj = stown( i1, i2 )
|
|
if( jj > 0 ) ngp( jj ) = ngp( jj ) + ngc( i ) - 1
|
|
jj = stowns( i1, i2 )
|
|
if( jj > 0 ) ngps( jj ) = ngps( jj ) + ngcs( i ) - 1
|
|
jj = stownw( i1, i2 )
|
|
if( jj > 0 ) ngpw( jj ) = ngpw( jj ) + ngcw( i ) - 1
|
|
ELSE
|
|
jj = stown( i1, i2 )
|
|
if( jj > 0 ) then
|
|
stown( -i1, -i2 ) = jj
|
|
ncp( jj ) = ncp( jj ) + 1
|
|
ngp( jj ) = ngp( jj ) + ngc( i )
|
|
end if
|
|
jj = stowns( i1, i2 )
|
|
if( jj > 0 ) then
|
|
stowns( -i1, -i2 ) = jj
|
|
ncps( jj ) = ncps( jj ) + 1
|
|
ngps( jj ) = ngps( jj ) + ngcs( i )
|
|
end if
|
|
jj = stownw( i1, i2 )
|
|
if( jj > 0 ) then
|
|
stownw( -i1, -i2 ) = jj
|
|
ncpw( jj ) = ncpw( jj ) + 1
|
|
ngpw( jj ) = ngpw( jj ) + ngcw( i )
|
|
end if
|
|
END IF
|
|
END DO
|
|
|
|
END IF
|
|
|
|
IF( ALLOCATED( sticks_owner ) ) DEALLOCATE( sticks_owner )
|
|
ALLOCATE( sticks_owner( lb(1): ub(1), lb(2):ub(2) ) )
|
|
|
|
sticks_owner( :, : ) = ABS( stown( :, :) )
|
|
|
|
RETURN
|
|
END SUBROUTINE
|
|
|
|
!=----------------------------------------------------------------------=
|
|
|
|
|
|
SUBROUTINE pstickset( dfftp, dffts, alat, a1, a2, a3, gcut, gkcut, gcuts, &
|
|
nr1, nr2, nr3, nr1x, nr2x, nr3x, nr1s, nr2s, nr3s, nr1sx, nr2sx, nr3sx, &
|
|
ngw, ngm, ngs )
|
|
|
|
USE kinds, ONLY: dbl
|
|
USE mp_global, ONLY: mpime, nproc, group
|
|
USE mp, ONLY: mp_max
|
|
USE control_flags, ONLY: gamma_only
|
|
USE io_global, ONLY: ionode
|
|
USE io_global, ONLY: stdout
|
|
USE fft_types, ONLY: fft_dlay_descriptor, fft_dlay_allocate, fft_dlay_set, &
|
|
fft_dlay_scalar
|
|
|
|
|
|
TYPE(fft_dlay_descriptor), INTENT(INOUT) :: dfftp, dffts
|
|
REAL(dbl), INTENT(IN) :: a1(3), a2(3), a3(3), alat
|
|
REAL(dbl), INTENT(IN) :: gcut, gkcut, gcuts
|
|
INTEGER, INTENT(IN) :: nr1, nr2, nr3, nr1x, nr2x, nr3x
|
|
INTEGER, INTENT(IN) :: nr1s, nr2s, nr3s, nr1sx, nr2sx, nr3sx
|
|
INTEGER, INTENT(OUT) :: ngw, ngm, ngs
|
|
|
|
LOGICAL :: tk
|
|
! ... tk logical flag, TRUE if the symulation does not have the
|
|
! ... GAMMA symmetry
|
|
|
|
REAL(dbl) :: b1(3), b2(3), b3(3)
|
|
! ... b1, b2, b3 reciprocal space base vectors.
|
|
|
|
INTEGER :: ub(3), lb(3)
|
|
! ... ub(i), lb(i) upper and lower miller indexes
|
|
|
|
!
|
|
! ... Plane Waves
|
|
!
|
|
|
|
INTEGER, ALLOCATABLE :: stw(:,:)
|
|
! ... stick map (wave functions), stw(i,j) = number of G-vector in the
|
|
! ... stick whose x and y miller index are i and j
|
|
|
|
INTEGER, ALLOCATABLE :: nstpw(:)
|
|
! ... number of sticks (wave functions), nstpw(ip) = number of stick
|
|
! ... for processor ip
|
|
|
|
INTEGER, ALLOCATABLE :: sstpw(:)
|
|
! ... number of G-vectors (wave functions), sstpw(ip) = sum of the
|
|
! ... sticks lenght for processor ip = number of G-vectors
|
|
! ... owned by the processor ip
|
|
|
|
INTEGER :: nstw, nstpwx
|
|
! ... nstw local number of sticks (wave functions)
|
|
! ... nstpwx maximum among all processors of nstw
|
|
|
|
!
|
|
! ... Potentials
|
|
!
|
|
|
|
INTEGER, ALLOCATABLE :: st(:,:)
|
|
! ... stick map (potentials), st(i,j) = number of G-vector in the
|
|
! ... stick whose x and y miller index are i and j
|
|
|
|
INTEGER, ALLOCATABLE :: nstp(:)
|
|
! ... number of sticks (potentials), nstp(ip) = number of stick
|
|
! ... for processor ip
|
|
|
|
INTEGER, ALLOCATABLE :: sstp(:)
|
|
! ... number of G-vectors (potentials), sstp(ip) = sum of the
|
|
! ... sticks lenght for processor ip = number of G-vectors
|
|
! ... owned by the processor ip
|
|
|
|
INTEGER :: nst, nstpx
|
|
! ... nst local number of sticks (potentials)
|
|
! ... nstpx maximum among all processors of nst
|
|
|
|
!
|
|
! ... Smooth Mesh
|
|
!
|
|
|
|
INTEGER, ALLOCATABLE :: sts(:,:)
|
|
! ... stick map (smooth mesh), sts(i,j) = number of G-vector in the
|
|
! ... stick whose x and y miller index are i and j
|
|
|
|
INTEGER, ALLOCATABLE :: nstps(:)
|
|
! ... number of sticks (smooth mesh), nstp(ip) = number of stick
|
|
! ... for processor ip
|
|
|
|
INTEGER, ALLOCATABLE :: sstps(:)
|
|
! ... number of G-vectors (smooth mesh), sstps(ip) = sum of the
|
|
! ... sticks lenght for processor ip = number of G-vectors
|
|
! ... owned by the processor ip
|
|
|
|
INTEGER :: nsts, nstpsx
|
|
! ... nsts local number of sticks (smooth mesh)
|
|
! ... nstpsx maximum among all processors of nst
|
|
|
|
|
|
INTEGER, ALLOCATABLE :: ist(:,:) ! sticks indexes ordered
|
|
|
|
|
|
|
|
INTEGER :: i, j, k
|
|
INTEGER :: ip, is, itmp, iss, i1, i2, ngm_ , ngs_
|
|
INTEGER, ALLOCATABLE :: ist_tmp(:), index(:)
|
|
|
|
tk = .NOT. gamma_only
|
|
ub(1) = ( nr1 - 1 ) / 2
|
|
ub(2) = ( nr2 - 1 ) / 2
|
|
ub(3) = ( nr3 - 1 ) / 2
|
|
lb = - ub
|
|
|
|
! ... reciprocal lattice generators
|
|
|
|
CALL recips( a1, a2, a3, b1, b2, b3 )
|
|
b1 = b1 * alat
|
|
b2 = b2 * alat
|
|
b3 = b3 * alat
|
|
|
|
! ... Allocate maps
|
|
|
|
ALLOCATE( stw ( lb(1):ub(1), lb(2):ub(2) ) )
|
|
ALLOCATE( st ( lb(1):ub(1), lb(2):ub(2) ) )
|
|
ALLOCATE( sts ( lb(1):ub(1), lb(2):ub(2) ) )
|
|
|
|
st = 0
|
|
stw = 0
|
|
sts = 0
|
|
|
|
! ... Fill in the stick maps, for given g-space base (b1,b2,b3) and cut-off
|
|
|
|
CALL sticks_maps( tk, ub, lb, b1, b2, b3, gcut, gkcut, gcuts, st, stw, sts )
|
|
|
|
! ... Now count the number of stick nst and nstw
|
|
|
|
nst = COUNT( st > 0 )
|
|
nstw = COUNT( stw > 0 )
|
|
nsts = COUNT( sts > 0 )
|
|
|
|
IF (ionode) THEN
|
|
WRITE( stdout,*)
|
|
WRITE( stdout,10)
|
|
10 FORMAT(3X,'Stick Mesh',/, &
|
|
3X,'----------')
|
|
WRITE( stdout,15) nst, nstw, nsts
|
|
15 FORMAT( 3X, 'nst =', I6, ', nstw =', I6, ', nsts =', I6 )
|
|
END IF
|
|
|
|
ALLOCATE(ist(nst,5))
|
|
|
|
ALLOCATE(nstp(nproc))
|
|
ALLOCATE(sstp(nproc))
|
|
|
|
ALLOCATE(nstpw(nproc))
|
|
ALLOCATE(sstpw(nproc))
|
|
|
|
ALLOCATE(nstps(nproc))
|
|
ALLOCATE(sstps(nproc))
|
|
|
|
! ... initialize the sticks indexes array ist
|
|
|
|
CALL sticks_countg( tk, ub, lb, st, stw, sts, &
|
|
ist(:,1), ist(:,2), ist(:,4), ist(:,3), ist(:,5) )
|
|
|
|
! ... Sorts the sticks according to their lenght
|
|
|
|
ALLOCATE( index( nst ) )
|
|
|
|
CALL sticks_sort( ist(:,4), ist(:,3), ist(:,5), nst, index )
|
|
|
|
! ... Set as first stick the stick containing the G=0
|
|
!
|
|
! DO iss = 1, nst
|
|
! IF( ist( index( iss ), 1 ) == 0 .AND. ist( index( iss ), 2 ) == 0 ) EXIT
|
|
! END DO
|
|
! itmp = index( 1 )
|
|
! index( 1 ) = index( iss )
|
|
! index( iss ) = itmp
|
|
|
|
CALL sticks_dist( tk, ub, lb, index, ist(:,1), ist(:,2), ist(:,4), ist(:,3), ist(:,5), &
|
|
nst, nstp, nstpw, nstps, sstp, sstpw, sstps, st, stw, sts )
|
|
|
|
ngw = sstpw( mpime + 1 )
|
|
ngm = sstp( mpime + 1 )
|
|
ngs = sstps( mpime + 1 )
|
|
|
|
CALL sticks_pairup( tk, ub, lb, index, ist(:,1), ist(:,2), ist(:,4), ist(:,3), ist(:,5), &
|
|
nst, nstp, nstpw, nstps, sstp, sstpw, sstps, st, stw, sts )
|
|
|
|
! ... Allocate and Set fft data layout descriptors
|
|
|
|
#if defined __PARA
|
|
|
|
CALL fft_dlay_allocate( dfftp, nproc, nr1x, nr2x )
|
|
CALL fft_dlay_allocate( dffts, nproc, nr1sx, nr2sx )
|
|
|
|
CALL fft_dlay_set( dfftp, tk, nst, nr1, nr2, nr3, nr1x, nr2x, nr3x, (mpime+1), &
|
|
nproc, ub, lb, index, ist(:,1), ist(:,2), nstp, nstpw, sstp, sstpw, st, stw )
|
|
CALL fft_dlay_set( dffts, tk, nsts, nr1s, nr2s, nr3s, nr1sx, nr2sx, nr3sx, (mpime+1), &
|
|
nproc, ub, lb, index, ist(:,1), ist(:,2), nstps, nstpw, sstps, sstpw, sts, stw )
|
|
|
|
#else
|
|
|
|
DEALLOCATE( stw )
|
|
ALLOCATE( stw( lb(2) : ub(2), lb(3) : ub(3) ) )
|
|
|
|
CALL sticks_maps_scalar( (.not.tk), ub, lb, b1, b2, b3, gcut, gkcut, gcuts, stw, ngm_ , ngs_ )
|
|
|
|
IF( ngm_ /= ngm ) CALL errore( ' pstickset ', ' inconsistent ngm ', ABS( ngm - ngm_ ) )
|
|
IF( ngs_ /= ngs ) CALL errore( ' pstickset ', ' inconsistent ngs ', ABS( ngs - ngs_ ) )
|
|
|
|
CALL fft_dlay_allocate( dfftp, nproc, MAX(nr1x, nr3x), nr2x )
|
|
CALL fft_dlay_allocate( dffts, nproc, MAX(nr1sx, nr3sx), nr2sx )
|
|
|
|
CALL fft_dlay_scalar( dfftp, ub, lb, nr1, nr2, nr3, nr1x, nr2x, nr3x, stw )
|
|
CALL fft_dlay_scalar( dffts, ub, lb, nr1s, nr2s, nr3s, nr1sx, nr2sx, nr3sx, stw )
|
|
|
|
#endif
|
|
|
|
! ... Maximum number of sticks (potentials)
|
|
nstpx = MAXVAL( nstp )
|
|
! ... Maximum number of sticks (wave func.)
|
|
nstpwx = MAXVAL( nstpw )
|
|
|
|
IF (ionode) WRITE( stdout,119)
|
|
119 FORMAT(3X,' PEs n.st n.stw n.sts n.g n.gw n.gs')
|
|
DO ip = 1, nproc
|
|
IF (ionode) THEN
|
|
WRITE( stdout,120) ip, nstp(ip), nstpw(ip), nstps(ip), sstp(ip), sstpw(ip), sstps(ip)
|
|
END IF
|
|
END DO
|
|
IF (ionode) THEN
|
|
WRITE( stdout,120) 0, SUM(nstp), SUM(nstpw), SUM(nstps), SUM(sstp), SUM(sstpw), SUM(sstps)
|
|
END IF
|
|
120 FORMAT(3X,7I8)
|
|
|
|
|
|
DEALLOCATE( ist )
|
|
DEALLOCATE( index )
|
|
|
|
DEALLOCATE( st, stw, sts )
|
|
DEALLOCATE( sstp )
|
|
DEALLOCATE( nstp )
|
|
DEALLOCATE( sstpw )
|
|
DEALLOCATE( nstpw )
|
|
DEALLOCATE( sstps )
|
|
DEALLOCATE( nstps )
|
|
|
|
IF(ionode) WRITE( stdout,*)
|
|
|
|
RETURN
|
|
END SUBROUTINE pstickset
|
|
|
|
|
|
!=----------------------------------------------------------------------=
|
|
|
|
SUBROUTINE sticks_deallocate
|
|
IF( ALLOCATED( sticks_owner ) ) DEALLOCATE( sticks_owner )
|
|
RETURN
|
|
END SUBROUTINE
|
|
|
|
|
|
!=----------------------------------------------------------------------=
|
|
END MODULE stick_base
|
|
!=----------------------------------------------------------------------=
|