2004-11-25 22:51:47 +08:00
|
|
|
!
|
2005-05-17 03:19:04 +08:00
|
|
|
! Copyright (C) 2002-2005 FPMD-CPV groups
|
2004-11-25 22:51:47 +08:00
|
|
|
! 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 .
|
|
|
|
!
|
2007-01-03 17:04:02 +08:00
|
|
|
!
|
|
|
|
! Written and revised by Carlo Cavazzoni
|
|
|
|
! Task Groups parallelization by C. Bekas (IBM Research Zurich).
|
|
|
|
!
|
|
|
|
|
2004-11-25 22:51:47 +08:00
|
|
|
#include "f_defs.h"
|
|
|
|
|
|
|
|
|
2006-06-26 15:51:38 +08:00
|
|
|
!
|
|
|
|
!-------------------------------------------------------------------------
|
2007-01-03 17:04:02 +08:00
|
|
|
SUBROUTINE dforce_x ( i, bec, vkb, c, df, da, v, ldv, ispin, f, n, nspin, v1 )
|
2006-06-26 15:51:38 +08:00
|
|
|
!-----------------------------------------------------------------------
|
|
|
|
!computes: the generalized force df=CMPLX(dfr,dfi) acting on the i-th
|
|
|
|
! electron state at the gamma point of the brillouin zone
|
|
|
|
! represented by the vector c=CMPLX(cr,ci)
|
|
|
|
!
|
|
|
|
! d_n(g) = f_n { 0.5 g^2 c_n(g) + [vc_n](g) +
|
|
|
|
! sum_i,ij d^q_i,ij (-i)**l beta_i,i(g)
|
|
|
|
! e^-ig.r_i < beta_i,j | c_n >}
|
2006-08-29 17:40:12 +08:00
|
|
|
!
|
2007-01-03 17:04:02 +08:00
|
|
|
USE parallel_include
|
2006-08-29 17:40:12 +08:00
|
|
|
USE kinds, ONLY: dp
|
2007-02-26 22:48:03 +08:00
|
|
|
USE control_flags, ONLY: iprint, use_task_groups, program_name
|
2006-08-29 17:40:12 +08:00
|
|
|
USE gvecs, ONLY: nms, nps
|
|
|
|
USE cvan, ONLY: ish
|
|
|
|
USE uspp, ONLY: nhsa=>nkb, dvan, deeq
|
|
|
|
USE uspp_param, ONLY: nhm, nh
|
2006-06-26 15:51:38 +08:00
|
|
|
USE smooth_grid_dimensions, ONLY: nr1s, nr2s, nr3s, &
|
2006-08-29 17:40:12 +08:00
|
|
|
nr1sx, nr2sx, nr3sx, nnrsx
|
|
|
|
USE constants, ONLY: pi, fpi
|
|
|
|
USE ions_base, ONLY: nsp, na, nat
|
|
|
|
USE gvecw, ONLY: ngw, ggp
|
|
|
|
USE cell_base, ONLY: tpiba2
|
|
|
|
USE ensemble_dft, ONLY: tens
|
2007-01-03 17:04:02 +08:00
|
|
|
USE fft_base, ONLY: dffts
|
2006-08-29 17:40:12 +08:00
|
|
|
USE funct, ONLY: dft_is_meta
|
|
|
|
USE cp_interfaces, ONLY: fwfft, invfft
|
2007-01-03 17:04:02 +08:00
|
|
|
USE mp_global, ONLY: nogrp, me_image, ogrp_comm
|
2007-07-25 05:52:35 +08:00
|
|
|
USE task_groups, ONLY: tmp_npp, nolist, strd, nswx
|
2006-06-26 15:51:38 +08:00
|
|
|
!
|
|
|
|
IMPLICIT NONE
|
|
|
|
!
|
2007-01-03 17:04:02 +08:00
|
|
|
INTEGER, INTENT(IN) :: i
|
|
|
|
REAL(DP) :: bec(:,:)
|
|
|
|
COMPLEX(DP) :: vkb(:,:)
|
|
|
|
COMPLEX(DP) :: c(:,:)
|
|
|
|
COMPLEX(DP) :: df(:), da(:)
|
|
|
|
INTEGER, INTENT(IN) :: ldv
|
|
|
|
REAL(DP) :: v( ldv, * )
|
|
|
|
INTEGER :: ispin( : )
|
|
|
|
REAL(DP) :: f( : )
|
|
|
|
INTEGER, INTENT(IN) :: n, nspin
|
|
|
|
REAL(DP), OPTIONAL :: v1( ldv, * )
|
2006-06-26 15:51:38 +08:00
|
|
|
!
|
|
|
|
!
|
|
|
|
! local variables
|
|
|
|
!
|
2006-08-29 17:40:12 +08:00
|
|
|
INTEGER :: iv, jv, ia, is, isa, ism, ios, iss1, iss2, ir, ig, inl, jnl
|
2007-01-03 17:04:02 +08:00
|
|
|
INTEGER :: ivoff, jvoff, igoff, igno, igrp, ierr
|
|
|
|
INTEGER :: idx, eig_offset, eig_index, nogrp_
|
2007-07-25 05:52:35 +08:00
|
|
|
REAL(DP) :: fi, fip, dd, dv
|
2006-08-29 17:40:12 +08:00
|
|
|
COMPLEX(DP) :: fp, fm, ci
|
2007-09-17 17:42:39 +08:00
|
|
|
REAL(DP), ALLOCATABLE :: af( :, : ), aa( :, : )
|
2006-06-26 15:51:38 +08:00
|
|
|
COMPLEX(DP), ALLOCATABLE :: psi(:)
|
2007-09-17 17:42:39 +08:00
|
|
|
!
|
2006-06-26 15:51:38 +08:00
|
|
|
CALL start_clock( 'dforce' )
|
|
|
|
!
|
2007-01-03 17:04:02 +08:00
|
|
|
IF( use_task_groups ) THEN
|
|
|
|
nogrp_ = nogrp
|
|
|
|
ALLOCATE( psi( strd * ( nogrp + 1 ) ) )
|
|
|
|
ELSE
|
|
|
|
nogrp_ = 1
|
|
|
|
ALLOCATE( psi( nnrsx ) )
|
|
|
|
END IF
|
|
|
|
!
|
2007-09-17 17:42:39 +08:00
|
|
|
ci = ( 0.0d0, 1.0d0 )
|
2007-01-03 17:04:02 +08:00
|
|
|
!
|
2007-09-17 17:42:39 +08:00
|
|
|
psi( : ) = (0.d0, 0.d0)
|
2007-01-03 17:04:02 +08:00
|
|
|
|
|
|
|
igoff = 0
|
|
|
|
|
|
|
|
DO idx = 1, 2*nogrp_ , 2
|
2007-09-17 17:42:39 +08:00
|
|
|
!
|
|
|
|
! This loop is executed only ONCE when NOGRP=1.
|
|
|
|
! Equivalent to the case with no task-groups
|
|
|
|
! dfft%nsw(me) holds the number of z-sticks for the current processor per wave-function
|
|
|
|
! We can either send these in the group with an mpi_allgather...or put the
|
|
|
|
! in the PSIS vector (in special positions) and send them with them.
|
|
|
|
! Otherwise we can do this once at the beginning, before the loop.
|
|
|
|
! we choose to do the latter one.
|
|
|
|
!
|
|
|
|
! important: if n is odd => c(*,n+1)=0.
|
2007-01-03 17:04:02 +08:00
|
|
|
!
|
|
|
|
IF ( ( idx + i - 1 ) == n ) c( : , idx + i ) = 0.0d0
|
|
|
|
|
|
|
|
IF( idx + i - 1 <= n ) THEN
|
|
|
|
DO ig=1,ngw
|
|
|
|
psi(nms(ig)+igoff) = conjg( c(ig,idx+i-1) - ci * c(ig,idx+i) )
|
|
|
|
psi(nps(ig)+igoff) = c(ig,idx+i-1) + ci * c(ig,idx+i)
|
|
|
|
END DO
|
|
|
|
END IF
|
|
|
|
|
|
|
|
igoff = igoff + strd
|
|
|
|
|
2006-06-26 15:51:38 +08:00
|
|
|
END DO
|
|
|
|
|
2007-09-17 17:42:39 +08:00
|
|
|
CALL invfft( 'Wave', psi, nr1s, nr2s, nr3s, nr1sx, nr2sx, nr3sx )
|
2007-01-03 17:04:02 +08:00
|
|
|
!
|
|
|
|
! the following avoids a potential out-of-bounds error
|
|
|
|
!
|
|
|
|
IF ( i < n ) THEN
|
|
|
|
iss1 = ispin(i)
|
|
|
|
iss2 = ispin(i+1)
|
2006-06-26 15:51:38 +08:00
|
|
|
ELSE
|
2007-01-03 17:04:02 +08:00
|
|
|
iss1 = ispin(i)
|
|
|
|
iss2 = iss1
|
2006-06-26 15:51:38 +08:00
|
|
|
END IF
|
2007-09-17 17:42:39 +08:00
|
|
|
!
|
2007-01-03 17:04:02 +08:00
|
|
|
IF( use_task_groups ) THEN
|
2006-08-29 17:40:12 +08:00
|
|
|
!
|
2007-01-03 17:04:02 +08:00
|
|
|
DO ir = 1, nr1sx * nr2sx * tmp_npp( me_image + 1 )
|
|
|
|
psi(ir) = CMPLX( v(ir,iss1) * DBLE( psi(ir) ), v(ir,iss2) * AIMAG( psi(ir) ) )
|
|
|
|
END DO
|
2006-08-29 17:40:12 +08:00
|
|
|
!
|
2007-01-03 17:04:02 +08:00
|
|
|
ELSE
|
|
|
|
!
|
|
|
|
IF( PRESENT( v1 ) ) THEN
|
|
|
|
DO ir=1,nnrsx
|
|
|
|
psi(ir)=CMPLX(v(ir,iss1)* DBLE(psi(ir)), v1(ir,iss2)*AIMAG(psi(ir)) )
|
|
|
|
END DO
|
2006-08-29 17:40:12 +08:00
|
|
|
ELSE
|
2007-01-03 17:04:02 +08:00
|
|
|
DO ir=1,nnrsx
|
|
|
|
psi(ir)=CMPLX(v(ir,iss1)* DBLE(psi(ir)), v(ir,iss2)*AIMAG(psi(ir)) )
|
|
|
|
END DO
|
2006-08-29 17:40:12 +08:00
|
|
|
END IF
|
|
|
|
!
|
2007-01-03 17:04:02 +08:00
|
|
|
END IF
|
2006-06-26 15:51:38 +08:00
|
|
|
!
|
2007-09-17 17:42:39 +08:00
|
|
|
CALL fwfft( 'Wave', psi, nr1s, nr2s, nr3s, nr1sx, nr2sx, nr3sx )
|
2007-01-03 17:04:02 +08:00
|
|
|
!
|
2007-09-17 17:42:39 +08:00
|
|
|
! note : the factor 0.5 appears
|
2007-01-03 17:04:02 +08:00
|
|
|
! in the kinetic energy because it is defined as 0.5*g**2
|
|
|
|
! in the potential part because of the logics
|
|
|
|
!
|
2007-09-17 17:42:39 +08:00
|
|
|
! Each processor will treat its own part of the eigenstate
|
|
|
|
! assigned to its ORBITAL group
|
2007-01-03 17:04:02 +08:00
|
|
|
!
|
2006-06-26 15:51:38 +08:00
|
|
|
eig_offset = 0
|
2007-01-03 17:04:02 +08:00
|
|
|
igno = 1
|
|
|
|
|
|
|
|
DO idx = 1, 2*nogrp_ , 2
|
|
|
|
|
2006-12-18 07:32:38 +08:00
|
|
|
IF( idx + i - 1 <= n ) THEN
|
2007-01-03 17:04:02 +08:00
|
|
|
if (tens) then
|
|
|
|
fi = -0.5d0
|
|
|
|
fip = -0.5d0
|
|
|
|
else
|
|
|
|
fi = -0.5d0*f(i+idx-1)
|
|
|
|
fip = -0.5d0*f(i+idx)
|
|
|
|
endif
|
|
|
|
IF( use_task_groups ) THEN
|
|
|
|
DO ig=1,ngw
|
2007-09-17 17:42:39 +08:00
|
|
|
fp= psi(nps(ig)+eig_offset) + psi(nms(ig)+eig_offset)
|
|
|
|
fm= psi(nps(ig)+eig_offset) - psi(nms(ig)+eig_offset)
|
2007-01-03 17:04:02 +08:00
|
|
|
df(igno)= fi *(tpiba2 * ggp(ig) * c(ig,idx+i-1)+cmplx(real (fp), aimag(fm)))
|
|
|
|
da(igno)= fip*(tpiba2 * ggp(ig) * c(ig,idx+i )+cmplx(aimag(fp),-real (fm)))
|
|
|
|
igno = igno + 1
|
|
|
|
END DO
|
|
|
|
ELSE
|
|
|
|
DO ig=1,ngw
|
|
|
|
fp= psi(nps(ig)) + psi(nms(ig))
|
|
|
|
fm= psi(nps(ig)) - psi(nms(ig))
|
|
|
|
df(ig)= fi*(tpiba2*ggp(ig)* c(ig,idx+i-1)+CMPLX(DBLE(fp), AIMAG(fm)))
|
|
|
|
da(ig)=fip*(tpiba2*ggp(ig)* c(ig,idx+i )+CMPLX(AIMAG(fp),-DBLE(fm)))
|
|
|
|
END DO
|
|
|
|
END IF
|
2006-12-18 07:32:38 +08:00
|
|
|
END IF
|
2007-01-03 17:04:02 +08:00
|
|
|
|
2006-06-26 15:51:38 +08:00
|
|
|
eig_offset = eig_offset + nr3sx * dffts%nsw(me_image+1)
|
2007-09-17 17:42:39 +08:00
|
|
|
|
|
|
|
! We take into account the number of elements received from other members of the orbital group
|
2007-01-03 17:04:02 +08:00
|
|
|
|
2006-06-26 15:51:38 +08:00
|
|
|
ENDDO
|
|
|
|
|
2007-01-03 17:04:02 +08:00
|
|
|
!
|
|
|
|
IF(dft_is_meta()) THEN
|
|
|
|
CALL dforce_meta(c(1,i),c(1,i+1),df,da,psi,iss1,iss2,fi,fip) !METAGGA
|
|
|
|
END IF
|
|
|
|
|
|
|
|
|
2006-06-26 15:51:38 +08:00
|
|
|
IF( nhsa > 0 ) THEN
|
2007-01-03 17:04:02 +08:00
|
|
|
!
|
|
|
|
! aa_i,i,n = sum_j d_i,ij <beta_i,j|c_n>
|
|
|
|
!
|
|
|
|
ALLOCATE( af( nhsa, nogrp_ ), aa( nhsa, nogrp_ ) )
|
|
|
|
|
|
|
|
af = 0.0d0
|
|
|
|
aa = 0.0d0
|
|
|
|
!
|
|
|
|
igrp = 1
|
|
|
|
|
|
|
|
DO idx = 1, 2*nogrp_ , 2
|
2006-06-26 15:51:38 +08:00
|
|
|
|
2006-12-18 07:32:38 +08:00
|
|
|
IF( idx + i - 1 <= n ) THEN
|
|
|
|
|
2007-01-03 17:04:02 +08:00
|
|
|
IF (tens) THEN
|
|
|
|
fi = 1.0d0
|
|
|
|
fip= 1.0d0
|
|
|
|
ELSE
|
|
|
|
fi = f(i+idx-1)
|
|
|
|
fip= f(i+idx)
|
|
|
|
END IF
|
|
|
|
!
|
|
|
|
DO is = 1, nsp
|
|
|
|
DO iv = 1, nh(is)
|
2007-02-26 22:48:03 +08:00
|
|
|
IF( program_name == 'FPMD' ) THEN
|
|
|
|
ivoff = ish(is) + (iv-1) * na(is)
|
|
|
|
dd = dvan( iv, iv, is )
|
|
|
|
DO inl = ivoff + 1, ivoff + na(is)
|
|
|
|
af(inl,igrp) = af(inl,igrp) - fi * dd * bec(inl,i+idx-1)
|
|
|
|
END DO
|
|
|
|
IF( i + idx - 1 /= n ) THEN
|
|
|
|
DO inl = ivoff + 1, ivoff + na(is)
|
|
|
|
aa(inl,igrp) = aa(inl,igrp) - fip * dd * bec(inl,i+idx)
|
|
|
|
END DO
|
|
|
|
END IF
|
|
|
|
ELSE
|
2007-01-03 17:04:02 +08:00
|
|
|
DO jv = 1, nh(is)
|
|
|
|
isa = 0
|
|
|
|
DO ism = 1, is-1
|
|
|
|
isa = isa + na( ism )
|
|
|
|
END DO
|
2007-07-25 05:52:35 +08:00
|
|
|
dv = dvan(iv,jv,is)
|
2007-01-03 17:04:02 +08:00
|
|
|
ivoff = ish(is)+(iv-1)*na(is)
|
|
|
|
jvoff = ish(is)+(jv-1)*na(is)
|
|
|
|
IF( i + idx - 1 /= n ) THEN
|
|
|
|
DO ia=1,na(is)
|
|
|
|
inl = ivoff + ia
|
|
|
|
jnl = jvoff + ia
|
|
|
|
isa = isa + 1
|
2007-07-25 05:52:35 +08:00
|
|
|
dd = deeq(iv,jv,isa,iss1) + dv
|
2007-01-03 17:04:02 +08:00
|
|
|
af(inl,igrp) = af(inl,igrp) - fi * dd * bec(jnl,i+idx-1)
|
2007-07-25 05:52:35 +08:00
|
|
|
dd = deeq(iv,jv,isa,iss2) + dv
|
2007-01-03 17:04:02 +08:00
|
|
|
aa(inl,igrp) = aa(inl,igrp) - fip * dd * bec(jnl,i+idx)
|
|
|
|
END DO
|
|
|
|
ELSE
|
|
|
|
DO ia=1,na(is)
|
|
|
|
inl = ivoff + ia
|
|
|
|
jnl = jvoff + ia
|
|
|
|
isa = isa + 1
|
2007-07-25 05:52:35 +08:00
|
|
|
dd = deeq(iv,jv,isa,iss1) + dv
|
2007-01-03 17:04:02 +08:00
|
|
|
af(inl,igrp) = af(inl,igrp) - fi * dd * bec(jnl,i+idx-1)
|
|
|
|
END DO
|
|
|
|
END IF
|
|
|
|
END DO
|
2007-02-26 22:48:03 +08:00
|
|
|
END IF
|
2007-01-03 17:04:02 +08:00
|
|
|
END DO
|
|
|
|
END DO
|
2006-12-18 07:32:38 +08:00
|
|
|
|
|
|
|
END IF
|
2006-06-26 15:51:38 +08:00
|
|
|
|
2007-01-03 17:04:02 +08:00
|
|
|
igrp = igrp + 1
|
2006-06-26 15:51:38 +08:00
|
|
|
|
2007-01-03 17:04:02 +08:00
|
|
|
END DO
|
|
|
|
!
|
|
|
|
CALL DGEMM ( 'N', 'N', 2*ngw, nogrp_ , nhsa, 1.0d0, vkb, 2*ngw, af, nhsa, 1.0d0, df, 2*ngw)
|
2006-06-26 15:51:38 +08:00
|
|
|
|
2007-01-03 17:04:02 +08:00
|
|
|
CALL DGEMM ( 'N', 'N', 2*ngw, nogrp_ , nhsa, 1.0d0, vkb, 2*ngw, aa, nhsa, 1.0d0, da, 2*ngw)
|
|
|
|
!
|
|
|
|
DEALLOCATE( aa, af )
|
|
|
|
!
|
|
|
|
ENDIF
|
2006-06-26 15:51:38 +08:00
|
|
|
|
|
|
|
DEALLOCATE( psi )
|
2006-08-29 17:40:12 +08:00
|
|
|
!
|
2007-01-03 17:04:02 +08:00
|
|
|
CALL stop_clock( 'dforce' )
|
2006-08-29 17:40:12 +08:00
|
|
|
!
|
2007-01-03 17:04:02 +08:00
|
|
|
RETURN
|
|
|
|
END SUBROUTINE dforce_x
|
|
|
|
|