quantum-espresso/CPV/wf.f90

3123 lines
87 KiB
Fortran
Raw Blame History

!
! Copyright (C) 2002-2005 Quantum ESPRESSO 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 .
!
!
#define ZERO ( 0.D0, 0.D0 )
#define ONE ( 1.D0, 0.D0 )
#define CI ( 0.D0, 1.D0 )
!
! ... written by Manu Sharma ( 2001-2005 )
!
!----------------------------------------------------------------------------
SUBROUTINE wf( clwf, c, bec, eigr, eigrb, taub, irb, &
b1, b2, b3, Uall, what1, wfc, jw, ibrav )
!----------------------------------------------------------------------------
!
! ... this routine calculates overlap matrices
!
! ... routine makes use of c(-g)=c*(g) and beta(-g)=beta*(g)
!
USE kinds, ONLY : DP
USE constants, ONLY : pi, tpi
USE ions_base, ONLY : nsp, na, nax, nat
USE cvan, ONLY : nvb, ish
USE cell_base, ONLY : omega, a1, a2, a3, alat, h, ainv
USE electrons_base, ONLY : nbspx, nbsp, nupdwn, iupdwn, nspin
USE gvecb, ONLY : npb, nmb, ngb
USE gvecw, ONLY : ngw
USE reciprocal_vectors, ONLY : gstart
USE smooth_grid_dimensions, ONLY : nnrsx
USE control_flags, ONLY : iprsta
USE qgb_mod, ONLY : qgb
USE wannier_base, ONLY : wfg, nw, weight, indexplus, indexplusz, &
indexminus, indexminusz, tag, tagp, &
expo, wfsd
USE grid_dimensions, ONLY : nr1, nr2, nr3
USE smallbox_grid_dimensions, ONLY : nnrbx
USE uspp_param, ONLY : nh, nhm
USE uspp, ONLY : nkb
USE io_global, ONLY : ionode, stdout
USE mp, ONLY : mp_barrier, mp_sum
USE mp_wave, ONLY : redistwf
USE mp_global, ONLY : nproc_image, me_image, root_image, intra_image_comm
USE cp_interfaces, ONLY : invfft
USE fft_base, ONLY : dfftp, dfftb
USE printout_base, ONLY : printout_base_open, printout_base_unit, &
printout_base_close
USE parallel_include
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: irb(3,nat), jw, ibrav, clwf
REAL(DP), INTENT(INOUT) :: bec(nkb,nbsp)
REAL(DP), INTENT(IN) :: b1(3), b2(3), b3(3), taub(3,nax)
COMPLEX(DP), INTENT(INOUT) :: c(ngw,nbspx)
COMPLEX(DP), INTENT(IN) :: eigr(ngw,nat), eigrb(ngb,nat)
REAL(DP), INTENT(INOUT) :: Uall(nbsp,nbsp)
LOGICAL, INTENT(IN) :: what1
REAL(DP), INTENT(OUT) :: wfc(3,nbsp)
!
REAL(DP), ALLOCATABLE :: becwf(:,:), temp3(:,:)
COMPLEX(DP), ALLOCATABLE :: cwf(:,:), bec2(:), bec3(:), bec2up(:)
COMPLEX(DP), ALLOCATABLE :: bec2dw(:), bec3up(:), bec3dw(:)
COMPLEX(DP), ALLOCATABLE :: c_m(:,:), c_p(:,:), c_psp(:,:)
COMPLEX(DP), ALLOCATABLE :: c_msp(:,:)
INTEGER, ALLOCATABLE :: tagz(:)
REAL(DP), ALLOCATABLE :: Uspin(:,:)
COMPLEX(DP), ALLOCATABLE :: X(:,:), Xsp(:,:), X2(:,:), X3(:,:)
COMPLEX(DP), ALLOCATABLE :: O(:,:,:), Ospin(:,:,:), Oa(:,:,:)
COMPLEX(DP), ALLOCATABLE :: qv(:)
REAL(DP), ALLOCATABLE :: gr(:,:), mt(:), mt0(:), wr(:), W(:,:), EW(:,:)
INTEGER, ALLOCATABLE :: f3(:), f4(:)
COMPLEX(DP), ALLOCATABLE :: U2(:,:)
!
INTEGER :: inl, jnl, iss, isa, is, ia, ijv, i, j, k, l, ig, &
ierr, ti, tj, tk, iv, jv, inw, iqv, ibig1, ibig2, &
ibig3, ir1, ir2, ir3, ir, m, &
ib, jb, total, nstat, jj, ngpww, irb3
REAL(DP) :: t1, t2, t3, taup(3)
REAL(DP) :: wrsq, wrsqmin
COMPLEX(DP) :: qvt
REAL (DP) :: temp_vec(3)
INTEGER :: adjust,ini, ierr1,nnn, me
INTEGER :: igx, igy, igz
REAL(DP) :: wfcx, wfcy, wfcz
REAL(DP) :: te(6)
INTEGER :: iunit
COMPLEX(DP), EXTERNAL :: boxdotgridcplx
!
#if defined (__PARA)
!
INTEGER :: proc, ntot, ncol, mc, ngpwpp(nproc_image)
INTEGER :: ncol1,nz1, nz_1
INTEGER :: nmin(3), nmax(3), n1,n2,nzx,nz,nz_
INTEGER :: nmin1(3), nmax1(3)
!
COMPLEX(DP), ALLOCATABLE :: psitot(:,:), psitot_pl(:,:)
COMPLEX(DP), ALLOCATABLE :: psitot_mi(:,:)
INTEGER, ALLOCATABLE :: ns(:)
!
#endif
!
CALL start_clock('wf_1')
!
me = me_image + 1
!
ALLOCATE( becwf(nkb,nbsp), temp3(nkb,nbsp), U2(nbsp,nbsp) )
ALLOCATE( cwf(ngw,nbspx), bec2(nbsp), bec3(nbsp), bec2up(nupdwn(1)) )
ALLOCATE( bec3up( nupdwn(1) ) )
IF( nspin == 2 ) THEN
ALLOCATE( bec2dw( nupdwn(2) ), bec3dw( nupdwn(2) ) )
ENDIF
!
te = 0.D0
!
ALLOCATE( tagz( nw ))
!
tagz(:) = 1
tagz(3) = 0
!
! ... set up matrix O
!
ALLOCATE( O( nw, nbsp, nbsp ), X( nbsp, nbsp ), Oa( nw, nbsp, nbsp ) )
!
IF ( nspin == 2 .AND. nvb > 0 ) THEN
!
ALLOCATE( X2( nupdwn(1), nupdwn(1) ) )
ALLOCATE( X3( nupdwn(2), nupdwn(2) ) )
!
END IF
!
#if defined (__PARA)
!
! Compute the number of states to each processor
!
ALLOCATE( ns( nproc_image ) )
ns = nbsp / nproc_image
DO j = 1, nbsp
IF( (j-1) < MOD( nbsp, nproc_image ) ) ns( j ) = ns( j ) + 1
END DO
IF(iprsta.GT.4) THEN
DO j=1,nproc_image
WRITE( stdout, * ) ns(j)
END DO
END IF
!
nstat = ns( me )
total = 0
DO proc=1,nproc_image
ngpwpp(proc)=(dfftp%nwl(proc)+1)/2
total=total+ngpwpp(proc)
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "I am proceessor", proc, "and i have ",ns(me)," states."
END IF
END DO
!
ALLOCATE(psitot(total,nstat))
ALLOCATE(psitot_pl(total,nstat))
ALLOCATE(psitot_mi(total,nstat))
ALLOCATE(c_p(ngw,nbspx))
ALLOCATE(c_m(ngw,nbspx))
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "All allocations done"
END IF
!
! ... Step 1. Communicate to all Procs so that each proc has all
! ... G-vectors and some states instead of all states and some
! ... G-vectors. This information is stored in the 1-d array
! ... psitot1.
!
! Step 2. Convert the 1-d array psitot1 into a 2-d array consistent with the
! original notation c(ngw,nbsp). Psitot contains ntot = SUM_Procs(ngw) G-vecs
! and nstat states instead of all nbsp states
!
!
CALL redistwf( c, psitot, ngpwpp, ns, intra_image_comm, 1 )
!
#endif
IF( clwf .EQ. 5 ) THEN
!
CALL write_psi( c, jw )
!
END IF
!
!
#if defined (__PARA)
!
! Step 3. do the translation of the 2-d array to get the transtalted
! arrays psitot_pl and psittot_mi, corresponding to G+G' and -G+G'
!
DO inw=1,nw
!
! Intermediate Check. If the translation is only along the z-direction
! no interprocessor communication and data rearrangement is required
! because each processor contains all the G- components in the z-dir.
!
IF(tagz(inw).EQ.0) THEN
DO i=1,nbsp
DO ig=1,ngw
IF(indexplusz(ig).EQ.-1) THEN
c_p(ig,i)=(0.D0,0.D0)
ELSE
c_p(ig,i)=c(indexplusz(ig),i)
END IF
IF(indexminusz(ig).EQ.-1) THEN
c_m(ig,i)=(0.D0,0.D0)
ELSE
c_m(ig,i)=CONJG(c(indexminusz(ig),i))
END IF
END DO
END DO
ELSE
DO i=1,ns(me)
DO ig=1,total
IF(indexplus(ig,inw).EQ.-1) THEN
psitot_pl(ig,i)=(0.D0,0.D0)
ELSE
IF(tagp(ig,inw).EQ.1) THEN
psitot_pl(ig,i)=CONJG(psitot(indexplus(ig,inw),i))
ELSE
psitot_pl(ig,i)=psitot(indexplus(ig,inw),i)
END IF
END IF
IF(indexminus(ig,inw).EQ.-1) THEN
psitot_mi(ig,i)=(0.D0,0.D0)
ELSE
IF(tag(ig,inw).EQ.1) THEN
psitot_mi(ig,i)=CONJG(psitot(indexminus(ig,inw),i))
ELSE
psitot_mi(ig,i)=psitot(indexminus(ig,inw),i)
END IF
END IF
END DO
END DO
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "Step 3. do the translation of the 2-d array...Done, wf"
END IF
!
! Step 4. Convert the 2-d arrays psitot_p and psitot_m into 1-d
! arrays
!
! Step 5. Redistribute among processors. The result is stored in 2-d
! arrays c_p and c_m consistent with the notation c(ngw,nbsp), such that
! c_p(j,i) contains the coeffiCIent for c(j,i) corresponding to G+G'
! and c_m(j,i) contains the coeffiCIent for c(j,i) corresponding to -G+G'
!
c_p = 0.D0
CALL redistwf( c_p, psitot_pl, ngpwpp, ns, intra_image_comm, -1 )
!
c_m = 0.D0
CALL redistwf( c_m, psitot_mi, ngpwpp, ns, intra_image_comm, -1 )
!
END IF
!
#else
!
ALLOCATE(c_p(ngw,nbspx))
ALLOCATE(c_m(ngw,nbspx))
DO inw=1,nw
IF(tagz(inw).EQ.0) THEN
DO i=1,nbsp
DO ig=1,ngw
IF(indexplusz(ig).EQ.-1) THEN
c_p(ig,i)=(0.D0,0.D0)
ELSE
c_p(ig,i)=c(indexplusz(ig),i)
END IF
IF(indexminusz(ig).EQ.-1) THEN
c_m(ig,i)=(0.D0,0.D0)
ELSE
c_m(ig,i)=CONJG(c(indexminusz(ig),i))
END IF
END DO
END DO
ELSE
DO i=1,nbsp
DO ig=1,ngw
IF(indexplus(ig,inw).EQ.-1) THEN
c_p(ig,i)=(0.D0,0.D0)
ELSE
IF(tagp(ig,inw).EQ.1) THEN
c_p(ig,i)=CONJG(c(indexplus(ig,inw),i))
ELSE
c_p(ig,i)=c(indexplus(ig,inw),i)
END IF
END IF
IF(indexminus(ig,inw).EQ.-1) THEN
c_m(ig,i)=(0.D0,0.D0)
ELSE
IF(tag(ig,inw).EQ.1) THEN
c_m(ig,i)=CONJG(c(indexminus(ig,inw),i))
ELSE
c_m(ig,i)=c(indexminus(ig,inw),i)
END IF
END IF
END DO
END DO
END IF
!
#endif
!
! ... Step 6. Calculate Overlaps
!
! ... Augmentation Part first
!
ALLOCATE( qv( nnrbx ) )
!
X = ZERO
!
isa = 1
DO is = 1, nvb
DO ia =1, na(is)
DO iv = 1, nh(is)
inl = ish(is) + (iv-1)*na(is) + ia
jv = iv
ijv=(jv-1)*jv/2 + iv
qv( 1 : nnrbx ) = 0.D0
DO ig=1,ngb
qv(npb(ig))=eigrb(ig,isa)*qgb(ig,ijv,is)
qv(nmb(ig))=CONJG(eigrb(ig,isa)*qgb(ig,ijv,is))
END DO
#ifdef __PARA
irb3=irb(3,isa)
#endif
CALL invfft('Box',qv,dfftb,isa)
iqv=1
qvt=(0.D0,0.D0)
qvt=boxdotgridcplx(irb(1,isa),qv,expo(1,inw))
#ifdef __PARA
CALL mp_sum( qvt, intra_image_comm )
#endif
!
IF (nspin.EQ.1) THEN
bec2(1:nbsp)=(0.D0,0.D0)
bec2(1:nbsp)=bec(inl,1:nbsp)*ONE
CALL ZSYRK('U','T',nbsp,1,qvt,bec2,1,ONE,X,nbsp)
ELSE
X2=(0.D0,0.D0)
X3=(0.D0,0.D0)
bec2up(1:nupdwn(1))=(0.D0,0.D0)
bec2up(1:nupdwn(1))=bec(inl,1:nupdwn(1))
CALL ZSYRK('U','T',nupdwn(1),1,qvt,bec2up,1,ONE,X2,nupdwn(1))
bec2dw(1:nupdwn(2))=(0.D0,0.D0)
bec2dw(1:nupdwn(2))=bec(inl,iupdwn(2):nbsp)
CALL ZSYRK('U','T',nupdwn(2),1,qvt,bec2dw,1,ONE,X3,nupdwn(2))
DO i = 1, nupdwn(1)
DO j=i, nupdwn(1)
X(i,j)=X(i,j)+X2(i,j)
END DO
END DO
DO i = 1,nupdwn(2)
DO j=i,nupdwn(2)
X(i+nupdwn(1),j+nupdwn(1)) =X(i+nupdwn(1),j+nupdwn(1)) + X3(i,j)
END DO
END DO
END IF
DO jv = iv+1, nh(is)
jnl = ish(is) + (jv-1)*na(is) + ia
ijv = (jv-1)*jv/2 + iv
qv( 1:nnrbx ) = 0.D0
DO ig=1,ngb
qv(npb(ig))=eigrb(ig,isa)*qgb(ig,ijv,is)
qv(nmb(ig))=CONJG(eigrb(ig,isa)*qgb(ig,ijv,is))
END DO
CALL invfft('Box',qv,dfftb,isa)
iqv=1
qvt=0.D0
qvt=boxdotgridcplx(irb(1,isa),qv,expo(1,inw))
#ifdef __PARA
CALL mp_sum( qvt, intra_image_comm )
#endif
!
IF (nspin.EQ.1) THEN
bec2(1:nbsp)=(0.D0,0.D0)
bec3(1:nbsp)=(0.D0,0.D0)
bec2(1:nbsp)=bec(inl,1:nbsp)*ONE
bec3(1:nbsp)=bec(jnl,1:nbsp)*ONE
CALL ZSYR2K('U','T',nbsp,1,qvt,bec2,1,bec3,1,ONE,X,nbsp)
ELSE
X2=(0.D0,0.D0)
X3=(0.D0,0.D0)
bec2up(1:nupdwn(1))=(0.D0,0.D0)
bec3up(1:nupdwn(1))=(0.D0,0.D0)
bec2up(1:nupdwn(1))=bec(inl,1:nupdwn(1))*ONE
bec3up(1:nupdwn(1))=bec(jnl,1:nupdwn(1))*ONE
CALL ZSYR2K('U','T',nupdwn(1),1,qvt,bec2up,1,bec3up,1,ONE,X2,nupdwn(1))
bec2dw(1:nupdwn(2))=(0.D0,0.D0)
bec3dw(1:nupdwn(2))=(0.D0,0.D0)
bec2dw(1:nupdwn(2))=bec(inl,iupdwn(2):nbsp)*ONE
bec3dw(1:nupdwn(2))=bec(jnl,iupdwn(2):nbsp)*ONE
CALL ZSYR2K('U','T',nupdwn(2),1,qvt,bec2dw,1,bec3dw,1,ONE,X3,nupdwn(2))
DO i = 1, nupdwn(1)
DO j=i, nupdwn(1)
X(i,j)=X(i,j)+X2(i,j)
END DO
END DO
DO i = 1,nupdwn(2)
DO j=i,nupdwn(2)
X(i+nupdwn(1),j+nupdwn(1)) =X(i+nupdwn(1),j+nupdwn(1)) + X3(i,j)
END DO
END DO
END IF
END DO
END DO
isa = isa + 1
END DO
END DO
t1=omega/DBLE(nr1*nr2*nr3)
X=X*t1
DO i=1, nbsp
DO j=i+1, nbsp
X(j, i)=X(i, j)
END DO
END DO
Oa(inw, :, :)=X(:, :)
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "Augmentation Part Done"
END IF
DEALLOCATE( qv )
! Then Soft Part
IF( nspin == 1 ) THEN
! Spin Unpolarized calculation
X=0.D0
IF( gstart == 2 ) THEN
c_m(1,:)=0.D0
END IF
! cwf(:,:)=ZERO
! cwf(:,:)=c(:,:)
CALL zgemm('C','N',nbsp,nbsp,ngw,ONE,c,ngw,c_p,ngw,ONE,X,nbsp)
CALL zgemm('T','N',nbsp,nbsp,ngw,ONE,c,ngw,c_m,ngw,ONE,X,nbsp)
CALL mp_sum ( X, intra_image_comm )
O(inw,:,:)=Oa(inw,:,:)+X(:,:)
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "Soft Part Done"
END IF
ELSE
! Spin Polarized case
! Up Spin First
ALLOCATE(Xsp(nbsp,nupdwn(1)))
ALLOCATE(c_psp(ngw,nupdwn(1)))
ALLOCATE(c_msp(ngw,nupdwn(1)))
Xsp=0.D0
c_psp=0.D0
c_msp=0.D0
DO i=1,nupdwn(1)
c_psp(:,i)=c_p(:,i)
c_msp(:,i)=c_m(:,i)
END DO
IF(gstart.EQ.2) THEN
c_msp(1,:)=0.D0
END IF
! cwf(:,:)=ZERO
! cwf(:,:)=c(:,:,1,1)
CALL zgemm('C','N',nbsp,nupdwn(1),ngw,ONE,c,ngw,c_psp,ngw,ONE,Xsp,nbsp)
CALL zgemm('T','N',nbsp,nupdwn(1),ngw,ONE,c,ngw,c_msp,ngw,ONE,Xsp,nbsp)
#ifdef __PARA
CALL mp_sum ( Xsp, intra_image_comm )
#endif
DO i=1,nupdwn(1)
DO j=1,nbsp
X(j,i)=Xsp(j,i)
END DO
END DO
DEALLOCATE(Xsp,c_psp,c_msp)
! Then Down Spin
ALLOCATE(Xsp(nbsp,iupdwn(2):nbsp))
ALLOCATE(c_psp(ngw,iupdwn(2):nbsp))
ALLOCATE(c_msp(ngw,iupdwn(2):nbsp))
Xsp=0.D0
c_psp=0.D0
c_msp=0.D0
DO i=iupdwn(2),nbsp
c_psp(:,i)=c_p(:,i)
c_msp(:,i)=c_m(:,i)
END DO
IF(gstart.EQ.2) THEN
c_msp(1,:)=0.D0
END IF
! cwf(:,:)=ZERO
! cwf(:,:)=c(:,:,1,1)
CALL zgemm('C','N',nbsp,nupdwn(2),ngw,ONE,c,ngw,c_psp,ngw,ONE,Xsp,nbsp)
CALL zgemm('T','N',nbsp,nupdwn(2),ngw,ONE,c,ngw,c_msp,ngw,ONE,Xsp,nbsp)
#ifdef __PARA
CALL mp_sum ( Xsp, intra_image_comm )
#endif
DO i=iupdwn(2),nbsp
DO j=1,nbsp
X(j,i)=Xsp(j,i)
END DO
END DO
DEALLOCATE(Xsp,c_psp,c_msp)
O(inw,:,:)=Oa(inw,:,:)+X(:,:)
END IF
END DO
#ifdef __PARA
DEALLOCATE(ns)
#endif
CALL stop_clock('wf_1')
DEALLOCATE( X )
IF ( ALLOCATED( X2 ) ) DEALLOCATE( X2 )
IF ( ALLOCATED( X3 ) ) DEALLOCATE( X3 )
!
CALL start_clock('wf_2')
IF(clwf.EQ.2) THEN
! output the overlap matrix to fort.38
IF(me.EQ.1) THEN
REWIND 38
WRITE(38, '(i5, 2i2, i3, f9.5)') nbsp, nw, nspin, ibrav, alat
IF (nspin.EQ.2) THEN
WRITE(38, '(i5)') nupdwn(1)
END IF
WRITE(38, *) a1
WRITE(38, *) a2
WRITE(38, *) a3
WRITE(38, *) b1
WRITE(38, *) b2
WRITE(38, *) b3
DO inw=1, nw
WRITE(38, *) wfg(inw, :), weight(inw)
END DO
DO inw=1, nw
DO i=1, nbsp
DO j=1, nbsp
WRITE(38, *) O(inw, i, j)
END DO
END DO
END DO
DO i=1, nbsp
DO j=1, nbsp
WRITE(38, *) Uall(i, j)
END DO
END DO
CLOSE(38)
END IF
CALL stop_run( .TRUE. )
END IF
IF(clwf.EQ.3.OR.clwf.EQ.4) THEN
IF(nspin.EQ.1) THEN
IF(.NOT.what1) THEN
IF(wfsd==1) THEN
CALL ddyn(nbsp,O,Uall,b1,b2,b3)
ELSE IF(wfsd==2) THEN
CALL wfsteep(nbsp,O,Uall,b1,b2,b3)
ELSE IF(wfsd==3) THEN
CALL jacobi_rotation(nbsp,O,Uall,b1,b2,b3)
END IF
END IF
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "Out from DDYN"
END IF
ELSE
ALLOCATE(Uspin(nupdwn(1), nupdwn(1)), Ospin(nw, nupdwn(1), nupdwn(1)))
DO i=1, nupdwn(1)
DO j=1, nupdwn(1)
Uspin(i, j)=Uall(i, j)
Ospin(:, i, j)=O(:, i, j)
END DO
END DO
IF(.NOT.what1) THEN
IF(wfsd==1) THEN
CALL ddyn(nupdwn(1), Ospin, Uspin,b1,b2,b3)
ELSE IF (wfsd==2) THEN
CALL wfsteep(nupdwn(1), Ospin, Uspin,b1,b2,b3)
ELSE
CALL jacobi_rotation(nupdwn(1), Ospin, Uspin,b1,b2,b3)
END IF
END IF
DO i=1, nupdwn(1)
DO j=1, nupdwn(1)
Uall(i, j)=Uspin(i, j)
O(:,i,j) =Ospin(:,i,j)
END DO
END DO
DEALLOCATE(Uspin, Ospin)
ALLOCATE(Uspin(nupdwn(2), nupdwn(2)), Ospin(nw, nupdwn(2), nupdwn(2)))
DO i=1, nupdwn(2)
DO j=1, nupdwn(2)
Uspin(i, j)=Uall(i+nupdwn(1), j+nupdwn(1))
Ospin(:, i, j)=O(:, i+nupdwn(1), j+nupdwn(1))
END DO
END DO
IF(.NOT.what1) THEN
IF(wfsd==1) THEN
CALL ddyn(nupdwn(2), Ospin, Uspin,b1,b2,b3)
ELSE IF (wfsd==2) THEN
CALL wfsteep(nupdwn(2), Ospin, Uspin,b1,b2,b3)
ELSE
CALL jacobi_rotation(nupdwn(2), Ospin, Uspin,b1,b2,b3)
END IF
END IF
DO i=1, nupdwn(2)
DO j=1, nupdwn(2)
Uall(i+nupdwn(1), j+nupdwn(1))=Uspin(i, j)
O(:,i+nupdwn(1),j+nupdwn(1))=Ospin(:,i,j)
END DO
END DO
DEALLOCATE(Uspin, Ospin)
END IF
END IF
! Update C and bec
cwf=ZERO
! cwf(:,:)=c(:,:,1,1)
becwf=0.0d0
U2=Uall*ONE
CALL zgemm('N','N',ngw,nbsp,nbsp,ONE,c,ngw,U2,nbsp,ZERO,cwf,ngw)
! call zgemm('nbsp','nbsp',ngw,nbsp,nbsp,ONE,cwf,ngw,U2,nbsp,ZERO,cwf,ngw)
CALL dgemm('N','N',nkb,nbsp,nbsp,ONE,bec,nkb,Uall,nbsp,ZERO,becwf,nkb)
U2=ZERO
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "Updating Wafefunctions and Bec"
END IF
c(:,:)=cwf(:,:)
bec(:,:)=becwf(:,:)
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "Wafefunctions and Bec Updated"
END IF
!
! calculate wannier-function centers
!
ALLOCATE( wr(nw), W(nw,nw), gr(nw,3), EW(nw,nw), f3(nw), f4(nw), mt0(nw), mt(nw) )
!
DO inw=1, nw
gr(inw, :)=wfg(inw,1)*b1(:)+wfg(inw,2)*b2(:)+wfg(inw,3)*b3(:)
END DO
!
! set up a matrix with the element (i,j) is G_i<5F>G_j<5F>weight(j)
! to check the correctness of choices on G vectors
!
DO i=1, nw
DO j=1, nw
W(i,j)=DOT_PRODUCT(gr(i,:),gr(j,:))*weight(j)
END DO
END DO
!
EW = W
DO i=1,nw
EW(i,i) = EW(i,i)-1.D0
END DO
!
! ... balance the phase factor if necessary
!
! adjust mt : very inefficient routine added by Young-Su -> must be improved
DO i=1, nbsp
mt0(:) = -AIMAG(LOG(O(:,i,i)))/tpi
wr = MATMUL(EW,mt0)
wrsq = SUM(wr(:)**2)
IF ( wrsq .lt. 1.D-6 ) THEN
mt = mt0
ELSE
wrsqmin = 100.D0
COMB: DO k=3**nw-1,0,-1
tk=k
DO j=nw,1,-1
f3(j)=tk/3**(j-1)
tk=tk-f3(j)*3**(j-1)
END DO
mt(:)=mt0(:)+f3(:)-1
wr = MATMUL(EW,mt)
wrsq = SUM(wr(:)**2)
IF ( wrsq .lt. wrsqmin ) THEN
wrsqmin = wrsq
f4(:)=f3(:)-1
END IF
END DO COMB
mt = mt0 + f4
END IF
!
wfc(1, i) = SUM(mt*weight(:)*gr(:,1))*alat
wfc(2, i) = SUM(mt*weight(:)*gr(:,2))*alat
wfc(3, i) = SUM(mt*weight(:)*gr(:,3))*alat
!
END DO
!
IF ( ionode ) THEN
!
iunit = printout_base_unit( "wfc" )
CALL printout_base_open( "wfc" )
IF ( .NOT. what1 ) THEN
!
! ... pbc are imposed here in the range [0,1]
!
DO i = 1, nbsp
!
temp_vec(:) = MATMUL( ainv(:,:), wfc(:,i) )
!
temp_vec(:) = temp_vec(:) - floor (temp_vec(:))
!
temp_vec(:) = MATMUL( h(:,:), temp_vec(:) )
!
WRITE( iunit, '(3f20.14)' ) temp_vec(:)
!
END DO
!
END IF
CALL printout_base_close( "wfc" )
!
END IF
!
!
!
DEALLOCATE( wr, W, gr, EW, f3, f4, mt0, mt )
!
#if defined (__PARA)
!
DEALLOCATE( psitot )
DEALLOCATE( psitot_pl )
DEALLOCATE( psitot_mi )
!
#endif
!
DEALLOCATE( c_p, c_m )
!
DEALLOCATE( O )
DEALLOCATE( Oa )
DEALLOCATE( tagz )
DEALLOCATE( becwf, temp3, U2 )
DEALLOCATE( cwf, bec2, bec3, bec2up, bec3up )
IF( ALLOCATED( bec2dw ) ) DEALLOCATE( bec2dw )
IF( ALLOCATED( bec3dw ) ) DEALLOCATE( bec3dw )
CALL stop_clock('wf_2')
!
RETURN
!
END SUBROUTINE wf
!
!----------------------------------------------------------------------------
SUBROUTINE ddyn( m, Omat, Umat, b1, b2, b3 )
!----------------------------------------------------------------------------
! ... This part of the subroutine wf has been added by Manu. It performes
! ... Damped Dynamics on the A matrix to get the Unitary transformation to
! ... obtain the wannier function at time(t+delta). It also updates the
! ... quantities bec
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE wannier_base, ONLY : wf_friction, nsteps, tolw, adapt, wf_q, &
weight, nw, wfdt
USE cell_base, ONLY : alat
USE constants, ONLY : tpi, autoaf => BOHR_RADIUS_ANGS
USE electrons_base, ONLY : nbsp
USE control_flags, ONLY : iprsta
USE mp_global, ONLY : me_image
USE printout_base, ONLY : printout_base_open, printout_base_unit, &
printout_base_close
USE parallel_include
!
IMPLICIT NONE
!
INTEGER :: f3(nw), f4(nw), i,j,inw
INTEGER ,INTENT(in) :: m
REAL(DP), INTENT(in) :: b1(3),b2(3),b3(3)
REAL(DP), INTENT(inout) :: Umat(m,m)
COMPLEX(DP), INTENT(inout) :: Omat(nw,m,m)
COMPLEX(DP) :: U2(m,m),U3(m,m)
INTEGER :: adjust,ini, ierr1,nnn
REAL(DP), ALLOCATABLE, DIMENSION(:) :: wr
REAL(DP), ALLOCATABLE, DIMENSION(:,:) :: W
REAL(DP) :: t0, fric,U(m,m), t2
REAL(DP) :: A(m,m),oldt0,Wm(m,m),U1(m,m)
REAL(DP) :: Aminus(m,m), Aplus(m,m),f2(4*m)
REAL(DP) :: temp(m,m)
COMPLEX(DP) :: d(m,m)
COMPLEX(DP) :: f1(2*m-1), wp(m*(m+1)/2),z(m,m)
COMPLEX(DP), ALLOCATABLE, DIMENSION(:, :) :: X1
COMPLEX(DP), ALLOCATABLE, DIMENSION(:, :, :) :: Oc
REAL(DP) , ALLOCATABLE , DIMENSION(:) :: mt
REAL(DP) :: spread, sp
REAL(DP) :: wfc(3,nbsp), gr(nw,3)
INTEGER :: me, iunit
!
me = me_image + 1
!
ALLOCATE(mt(nw))
ALLOCATE(X1(m,m))
ALLOCATE(Oc(nw,m,m))
fric=wf_friction
ALLOCATE (W(m,m),wr(m))
Umat=0.D0
DO i=1,m
Umat(i,i)=1.D0
END DO
U2=Umat*ONE
!
! update Oc using the initial guess of Uspin
!
DO inw=1, nw
X1(:, :)=Omat(inw, :, :)
U3=ZERO
CALL zgemm ('T', 'N', m,m,m,ONE,U2,m,X1,m,ZERO,U3,m)
X1=ZERO
CALL zgemm ('N','N', m,m,m,ONE,U3,m,U2,m,ZERO,X1,m)
Oc(inw, :, :)=X1(:, :)
END DO
U2=ZERO
U3=ZERO
oldt0=0.D0
A=0.D0
Aminus=A
temp=Aminus
! START ITERATIONS HERE
DO ini=1, nsteps
t0=0.D0 !use t0 to store the value of omega
DO inw=1, nw
DO i=1, m
t0=t0+DBLE(CONJG(Oc(inw, i, i))*Oc(inw, i, i))
END DO
END DO
IF(ABS(t0-oldt0).LT.tolw) THEN
IF(me.EQ.1) THEN
WRITE(27,*) "MLWF Generated at Step",ini
END IF
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "MLWF Generated at Step",ini
END IF
GO TO 241
END IF
IF(adapt) THEN
IF(oldt0.LT.t0) THEN
fric=fric/2.d0
A=Aminus
Aminus=temp
END IF
END IF
! calculate d(omega)/dA and store result in W
! this is the force for the damped dynamics
!
W=0.D0
DO inw=1, nw
t2=weight(inw)
DO i=1,m
DO j=1,m
W(i,j)=W(i,j)+t2*DBLE(Oc(inw,i,j)*CONJG(Oc(inw,i,i) &
-Oc(inw,j,j))+CONJG(Oc(inw,j,i))*(Oc(inw,i,i)-Oc(inw,j,j)))
END DO
END DO
END DO
! the verlet scheme to calculate A(t+wfdt)
Aplus=0.D0
DO i=1,m
DO j=i+1,m
Aplus(i,j)=Aplus(i,j)+(2*wfdt/(2*wfdt+fric))*(2*A(i,j) &
-Aminus(i,j)+(wfdt*wfdt/wf_q)*W(i,j)) + (fric/(2*wfdt+fric))*Aminus(i,j)
ENDDO
ENDDO
Aplus=Aplus-TRANSPOSE(Aplus)
Aplus=(Aplus-A)
DO i=1, m
DO j=i,m
wp(i + (j-1)*j/2) = CMPLX(0.d0, Aplus(i,j),kind=DP)
END DO
END DO
#if ! defined __ESSL
CALL zhpev('V','U',m,wp,wr,z,m,f1,f2,ierr1)
#else
CALL zhpev(21, wp, wr, z, m, m, f2, 4*m)
ierr1 = 0
#endif
IF (ierr1.NE.0) THEN
WRITE( stdout, * ) "failed to diagonalize W!"
STOP
END IF
d=0.D0
DO i=1, m
d(i, i)=EXP(CI*wr(i)*wfdt)
END DO !d=exp(d)
! U=z*exp(d)*z+
!
U3=ZERO
CALL zgemm ('N', 'N', m,m,m,ONE,z,m,d,m,ZERO,U3,m)
U2=ZERO
CALL zgemm ('N','C', m,m,m,ONE,U3,m,z,m,ZERO,U2,m)
U=DBLE(U2)
U2=ZERO
U3=ZERO
temp=Aminus
Aminus=A
A=Aplus
! update Umat
!
U1=ZERO
CALL dgemm ('N', 'N', m,m,m,ONE,Umat,m,U,m,ZERO,U1,m)
Umat=U1
! update Oc
!
U2=Umat*ONE
U3=ZERO
DO inw=1, nw
X1(:, :)=Omat(inw, :, :)
CALL zgemm ('T', 'N', m,m,m,ONE,U2,m,X1,m,ZERO,U3,m)
X1=ZERO
CALL zgemm ('N','N',m,m,m,ONE,U3,m,U2,m,ZERO,X1,m)
Oc(inw, :, :)=X1(:, :)
END DO
U2=ZERO
U3=ZERO
IF(ABS(t0-oldt0).GE.tolw.AND.ini.GE.nsteps) THEN
IF(me.EQ.1) THEN
WRITE(27,*) "MLWF Not generated after",ini,"Steps."
END IF
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "MLWF Not generated after",ini,"Steps."
END IF
GO TO 241
END IF
oldt0=t0
END DO
241 DEALLOCATE(wr, W)
spread=0.0d0
IF(me.EQ.1) THEN
iunit = printout_base_unit( "spr" )
CALL printout_base_open( "spr" )
END IF
DO i=1, m
!
mt=1.D0-DBLE(Oc(:,i,i)*CONJG(Oc(:,i,i)))
sp = (alat*autoaf/tpi)**2*SUM(mt*weight)
!
IF(me.EQ.1) THEN
WRITE(iunit, '(f10.7)') sp
END IF
IF ( sp < 0.D0 ) &
CALL errore( 'cp-wf', 'Something wrong WF Spread negative', 1 )
!
spread=spread+sp
!
END DO
IF(me.EQ.1) THEN
CALL printout_base_close( "spr" )
END IF
spread=spread/m
IF(me.EQ.1) THEN
WRITE(24, '(f10.7)') spread
WRITE(27,*) "Average spread = ", spread
END IF
Omat=Oc
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "Average spread = ", spread
END IF
!
DEALLOCATE (mt,X1,Oc)
!
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "Leaving DDYN"
END IF
RETURN
END SUBROUTINE ddyn
!
!----------------------------------------------------------------------------
SUBROUTINE wfunc_init( clwf, b1, b2, b3, ibrav )
!----------------------------------------------------------------------------
!
USE io_global, ONLY : stdout
USE kinds, ONLY : DP
USE reciprocal_vectors, ONLY : gx, mill_l, gstart
USE gvecw, ONLY : ngw
USE electrons_base, ONLY : nbsp
USE wannier_base, ONLY : gnx, gnn, indexplus, indexminus, &
indexplusz, indexminusz, tag, tagp, &
wfg, weight, nw
USE cvan, ONLY : nvb
USE mp, ONLY : mp_barrier, mp_bcast, mp_gather, mp_set_displs
USE mp_global, ONLY : nproc_image, me_image, intra_image_comm, root_image
USE fft_base, ONLY : dfftp
USE parallel_include
!
IMPLICIT NONE
!
REAL(DP), INTENT(in) :: b1(3),b2(3),b3(3)
INTEGER, INTENT(in) :: clwf, ibrav
#ifdef __PARA
INTEGER :: ntot, proc, ierr, i,j,inw,ngppp(nproc_image)
INTEGER :: ii,ig,displs(nproc_image)
#else
INTEGER :: ierr, i,j,inw, ntot
INTEGER :: ii,ig
#endif
REAL (DP), ALLOCATABLE:: bigg(:,:)
INTEGER, ALLOCATABLE :: bign(:,:)
INTEGER :: igcount,nw1,jj,nw2, in, kk
INTEGER, ALLOCATABLE :: i_1(:), j_1(:), k_1(:)
INTEGER :: ti, tj, tk
REAL(DP) ::t1, vt, err1, err2, err3
INTEGER :: ti1,tj1,tk1
INTEGER :: me
!
me = me_image + 1
!
IF ( nbsp < nproc_image ) &
CALL errore( 'cp-wf', &
& 'Number of Processors is greater than the number of states', 1 )
!
ALLOCATE(gnx(3,ngw))
ALLOCATE(gnn(3,ngw))
vt=1.0d-4
j=0
DO i=1,ngw
gnx(1,i)=gx(1,i)
gnx(2,i)=gx(2,i)
gnx(3,i)=gx(3,i)
gnn(1,i)=mill_l(1,i)
gnn(2,i)=mill_l(2,i)
gnn(3,i)=mill_l(3,i)
END DO
#ifdef __PARA
ntot=0
DO i=1,nproc_image
ngppp(i)=(dfftp%nwl(i)+1)/2
END DO
CALL mp_set_displs( ngppp, displs, ntot, nproc_image )
IF(me.EQ.1) THEN
ALLOCATE(bigg(3,ntot))
ALLOCATE(bign(3,ntot))
END IF
#else
ntot=ngw
ALLOCATE(bigg(3,ntot))
ALLOCATE(bign(3,ntot))
bigg(1:3,1:ntot)=gnx(1:3,1:ntot)
bign(1:3,1:ntot)=gnn(1:3,1:ntot)
#endif
!
CALL setwfg( ibrav, b1, b2, b3 )
!
nw1 = nw
WRITE( stdout, * ) "WANNIER SETUP : check G vectors and weights"
DO i=1,nw1
WRITE( stdout,'("inw = ",I1,":",3I4,F11.6)') i,wfg(i,:), weight(i)
END DO
WRITE( stdout, * ) "Translations to be done", nw1
ALLOCATE(indexplus(ntot,nw1))
ALLOCATE(indexminus(ntot,nw1))
ALLOCATE(tag(ntot,nw1))
ALLOCATE(tagp(ntot,nw1))
ALLOCATE(indexplusz(ngw))
ALLOCATE(indexminusz(ngw))
ALLOCATE(i_1(nw1))
ALLOCATE(j_1(nw1))
ALLOCATE(k_1(nw1))
indexplus=0
indexminus=0
tag=0
tagp=0
indexplusz=0
indexminusz=0
i_1(:)=wfg(:,1)
j_1(:)=wfg(:,2)
k_1(:)=wfg(:,3)
WRITE( stdout, * ) "ibrav selected:", ibrav
!
IF(nvb.GT.0) CALL small_box_wf(i_1, j_1, k_1, nw1)
#ifdef __PARA
!
CALL mp_barrier( intra_image_comm )
!
CALL mp_gather( gnx, bigg, ngppp, displs, root_image, intra_image_comm )
!
CALL mp_barrier( intra_image_comm )
!
CALL mp_gather( gnn, bign, ngppp, displs, root_image, intra_image_comm )
!
#endif
IF(me.EQ.1) THEN
IF(clwf.EQ.5) THEN
#ifdef __PARA
DO ii=1,ntot
WRITE(21,*) bigg(:,ii)
END DO
#else
DO ii=1,ngw
WRITE(21,*) gx(1,ii), gx(2,ii), gx(3,ii)
END DO
#endif
CLOSE(21)
END IF
END IF
DO inw=1,nw1
IF(i_1(inw).EQ.0.AND.j_1(inw).EQ.0) THEN
DO ig=1,ngw
IF(gstart.EQ.2) THEN
indexminusz(1)=-1
END IF
! ti=(gnn(1,ig)+i_1(inw))*b1(1)+(gnn(2,ig)+j_1(inw))*b2(1)+(gnn(3,ig)+k_1(inw))*b3(1)
! tj=(gnn(1,ig)+i_1(inw))*b1(2)+(gnn(2,ig)+j_1(inw))*b2(2)+(gnn(3,ig)+k_1(inw))*b3(2)
! tk=(gnn(1,ig)+i_1(inw))*b1(3)+(gnn(2,ig)+j_1(inw))*b2(3)+(gnn(3,ig)+k_1(inw))*b3(3)
ti=(gnn(1,ig)+i_1(inw))
tj=(gnn(2,ig)+j_1(inw))
tk=(gnn(3,ig)+k_1(inw))
DO ii=1,ngw
err1=ABS(gnx(1,ii)-ti)
err2=ABS(gnx(2,ii)-tj)
err3=ABS(gnx(3,ii)-tk)
IF(gnn(1,ii).EQ.ti.AND.gnn(2,ii).EQ.tj.AND.gnn(3,ii).EQ.tk) THEN
! if(err1.lt.vt.and.err2.lt.vt.and.err3.lt.vt) then
indexplusz(ig)=ii
! write (6,*) "Found +", ig,ii,inw, ti,tj,tk
! write (6,*) "looking for", ti,tj,tk
GO TO 224
ELSE
END IF
END DO
indexplusz(ig)=-1
! write (6,*) "Not Found +", ig,-1,inw
! write (6,*) "looking for", ti,tj,tk
!224 ti=(-gnn(1,ig)+i_1(inw))*b1(1)+(-gnn(2,ig)+j_1(inw))*b2(1)+(-gnn(3,ig)+k_1(inw))*b3(1)
! tj=(-gnn(1,ig)+i_1(inw))*b1(2)+(-gnn(2,ig)+j_1(inw))*b2(2)+(-gnn(3,ig)+k_1(inw))*b3(2)
! tk=(-gnn(1,ig)+i_1(inw))*b1(3)+(-gnn(2,ig)+j_1(inw))*b2(3)+(-gnn(3,ig)+k_1(inw))*b3(3)
224 ti=(-gnn(1,ig)+i_1(inw))
tj=(-gnn(2,ig)+j_1(inw))
tk=(-gnn(3,ig)+k_1(inw))
ti1=-gnn(1,ig)+i_1(inw)
tj1=-gnn(2,ig)+j_1(inw)
tk1=-gnn(3,ig)+k_1(inw)
IF(ti1.LT.0.OR.(ti1.EQ.0.AND.(tj1.LT.0.OR.(tj1.EQ.0.AND.tk1.LT.0)))) THEN
DO ii=1,ngw
err1=ABS(gnx(1,ii)+ti)
err2=ABS(gnx(2,ii)+tj)
err3=ABS(gnx(3,ii)+tk)
IF(gnn(1,ii).EQ.-ti.AND.gnn(2,ii).EQ.-tj.AND.gnn(3,ii).EQ.-tk) THEN
! if(err1.lt.vt.and.err2.lt.vt.and.err3.lt.vt) then
indexminusz(ig)=ii
! tag(ig,inw)=1
! write (6,*) "Found -", ig,ii,inw
! write (6,*) "looking for", -ti,-tj,-tk
GO TO 223
ELSE
END IF
END DO
indexminusz(ig)=-1
! tag(ig,inw)=1
! write (6,*) "Not Found -", ig,-1,inw
! write (6,*) "looking for", -ti,-tj,-tk
ELSE
DO ii=1,ngw
err1=ABS(gnx(1,ii)-ti)
err2=ABS(gnx(2,ii)-tj)
err3=ABS(gnx(3,ii)-tk)
IF(gnn(1,ii).EQ.ti.AND.gnn(2,ii).EQ.tj.AND.gnn(3,ii).EQ.tk) THEN
! if(err1.lt.vt.and.err2.lt.vt.and.err3.lt.vt) then
indexminusz(ig)=ii
! tag(ig,inw)=-1
! write (6,*) "Found -", ig,ii,inw
! write (6,*) "looking for", ti,tj,tk
GO TO 223
ELSE
END IF
END DO
indexminusz(ig)=-1
! tag(ig,inw)=-1
! write (6,*) "Not Found -", ig,-1,inw
! write (6,*) "looking for", ti,tj,tk
END IF
223 CONTINUE
END DO
WRITE( stdout, * ) "Translation", inw, "for", ngw, "G vectors"
ELSE
#ifdef __PARA
IF(me.EQ.1) THEN
#endif
DO ig=1,ntot
IF(gstart.EQ.2) THEN
indexminus(1,inw)=-1
END IF
! ti=(bign(1,ig)+i_1(inw))*b1(1)+(bign(2,ig)+j_1(inw))*b2(1)+(bign(3,ig)+k_1(inw))*b3(1)
! tj=(bign(1,ig)+i_1(inw))*b1(2)+(bign(2,ig)+j_1(inw))*b2(2)+(bign(3,ig)+k_1(inw))*b3(2)
! tk=(bign(1,ig)+i_1(inw))*b1(3)+(bign(2,ig)+j_1(inw))*b2(3)+(bign(3,ig)+k_1(inw))*b3(3)
ti=(bign(1,ig)+i_1(inw))
tj=(bign(2,ig)+j_1(inw))
tk=(bign(3,ig)+k_1(inw))
ti1=bign(1,ig)+i_1(inw)
tj1=bign(2,ig)+j_1(inw)
tk1=bign(3,ig)+k_1(inw)
IF(ti1.LT.0.OR.(ti1.EQ.0.AND.(tj1.LT.0.OR.(tj1.EQ.0.AND.tk1.LT.0)))) THEN
DO ii=1,ntot
err1=ABS(bigg(1,ii)+ti)
err2=ABS(bigg(2,ii)+tj)
err3=ABS(bigg(3,ii)+tk)
! if(err1.lt.vt.and.err2.lt.vt.and.err3.lt.vt) then
IF(bign(1,ii).EQ.-ti.AND.bign(2,ii).EQ.-tj.AND.bign(3,ii).EQ.-tk) THEN
indexplus(ig,inw)=ii
tagp(ig,inw)=1
! write (6,*) "Found +", ig,ii,inw
! write (6,*) "looking for", -ti,-tj,-tk
GO TO 214
ELSE
END IF
END DO
indexplus(ig,inw)=-1
tagp(ig,inw)=1
! write (6,*) "Not Found +", ig,-1,inw
! write (6,*) "looking for", -ti,-tj,-tk
ELSE
DO ii=1,ntot
err1=ABS(bigg(1,ii)-ti)
err2=ABS(bigg(2,ii)-tj)
err3=ABS(bigg(3,ii)-tk)
! if(err1.lt.vt.and.err2.lt.vt.and.err3.lt.vt) then
IF(bign(1,ii).EQ.ti.AND.bign(2,ii).EQ.tj.AND.bign(3,ii).EQ.tk) THEN
indexplus(ig,inw)=ii
tagp(ig,inw)=-1
! write (6,*) "Found +", ig,ii,inw
! write (6,*) "looking for", ti,tj,tk
GO TO 214
ELSE
END IF
END DO
indexplus(ig,inw)=-1
tagp(ig,inw)=-1
! write (6,*) "Not Found +", ig,-1,inw
! write (6,*) "looking for", ti,tj,tk
END IF
!214 ti=(-bign(1,ig)+i_1(inw))*b1(1)+(-bign(2,ig)+j_1(inw))*b2(1)+(-bign(3,ig)+k_1(inw))*b3(1)
! tj=(-bign(1,ig)+i_1(inw))*b1(2)+(-bign(2,ig)+j_1(inw))*b2(2)+(-bign(3,ig)+k_1(inw))*b3(2)
! tk=(-bign(1,ig)+i_1(inw))*b1(3)+(-bign(2,ig)+j_1(inw))*b2(3)+(-bign(3,ig)+k_1(inw))*b3(3)
214 ti=(-bign(1,ig)+i_1(inw))
tj=(-bign(2,ig)+j_1(inw))
tk=(-bign(3,ig)+k_1(inw))
ti1=-bign(1,ig)+i_1(inw)
tj1=-bign(2,ig)+j_1(inw)
tk1=-bign(3,ig)+k_1(inw)
IF(ti1.LT.0.OR.(ti1.EQ.0.AND.(tj1.LT.0.OR.(tj1.EQ.0.AND.tk1.LT.0)))) THEN
DO ii=1,ntot
err1=ABS(bigg(1,ii)+ti)
err2=ABS(bigg(2,ii)+tj)
err3=ABS(bigg(3,ii)+tk)
! if(err1.lt.vt.and.err2.lt.vt.and.err3.lt.vt) then
IF(bign(1,ii).EQ.-ti.AND.bign(2,ii).EQ.-tj.AND.bign(3,ii).EQ.-tk) THEN
indexminus(ig,inw)=ii
tag(ig,inw)=1
! write (6,*) "Found -", ig,ii,inw
! write (6,*) "looking for", -ti,-tj,-tk
GO TO 213
ELSE
END IF
END DO
indexminus(ig,inw)=-1
tag(ig,inw)=1
! write (6,*) "Not Found -", ig,-1,inw
! write (6,*) "looking for", -ti,-tj,-tk
ELSE
DO ii=1,ntot
err1=ABS(bigg(1,ii)-ti)
err2=ABS(bigg(2,ii)-tj)
err3=ABS(bigg(3,ii)-tk)
! if(err1.lt.vt.and.err2.lt.vt.and.err3.lt.vt) then
IF(bign(1,ii).EQ.ti.AND.bign(2,ii).EQ.tj.AND.bign(3,ii).EQ.tk) THEN
indexminus(ig,inw)=ii
tag(ig,inw)=-1
! write (6,*) "Found -", ig,ii,inw
! write (6,*) "looking for", ti,tj,tk
GO TO 213
ELSE
END IF
END DO
indexminus(ig,inw)=-1
tag(ig,inw)=-1
! write (6,*) "Not Found -", ig,-1,inw
! write (6,*) "looking for", ti,tj,tk
END IF
213 CONTINUE
END DO
WRITE( stdout, * ) "Translation", inw, "for", ntot, "G vectors"
#ifdef __PARA
END IF
#endif
END IF
END DO
#ifdef __PARA
CALL mp_barrier( intra_image_comm )
!
CALL mp_bcast( indexplus, root_image, intra_image_comm )
CALL mp_bcast( indexminus, root_image, intra_image_comm )
CALL mp_bcast( tag, root_image, intra_image_comm )
CALL mp_bcast( tagp, root_image, intra_image_comm )
IF (me.EQ.1) THEN
#endif
DEALLOCATE(bigg)
DEALLOCATE(bign)
#ifdef __PARA
END IF
#endif
DEALLOCATE(i_1,j_1,k_1)
RETURN
END SUBROUTINE wfunc_init
!
!----------------------------------------------------------------------------
SUBROUTINE grid_map()
!----------------------------------------------------------------------------
!
USE kinds, ONLY : DP
USE efcalc, ONLY : xdist, ydist, zdist
USE smooth_grid_dimensions, ONLY : nnrsx, nr1s, nr2s, nr3s, &
nr1sx, nr2sx, nr3sx
USE fft_base, ONLY : dffts
USE mp_global, ONLY : me_image
USE parallel_include
!
IMPLICIT NONE
!
INTEGER :: ir1, ir2, ir3, ibig3, me
!
me = me_image + 1
!
ALLOCATE(xdist(nnrsx))
ALLOCATE(ydist(nnrsx))
ALLOCATE(zdist(nnrsx))
!
DO ir3=1,nr3s
#ifdef __PARA
ibig3 = ir3 - dffts%ipp( me )
IF(ibig3.GT.0.AND.ibig3.LE.dffts%npp(me)) THEN
#else
ibig3=ir3
#endif
DO ir2=1,nr2s
DO ir1=1,nr1s
xdist(ir1+(ir2-1)*nr1sx+(ibig3-1)*nr1sx*nr2sx) = &
& ((ir1-1)/DBLE(nr1sx))
ydist(ir1+(ir2-1)*nr1sx+(ibig3-1)*nr1sx*nr2sx) = &
& ((ir2-1)/DBLE(nr2sx))
zdist(ir1+(ir2-1)*nr1sx+(ibig3-1)*nr1sx*nr2sx) = &
& ((ir3-1)/DBLE(nr3sx))
!
END DO
END DO
#ifdef __PARA
END IF
#endif
END DO
RETURN
END SUBROUTINE grid_map
!
!----------------------------------------------------------------------------
SUBROUTINE setwfg( ibrav, b1, b2, b3 )
!----------------------------------------------------------------------------
!
! ... added by Young-Su Lee ( Nov 2006 )
! Find G vectors for a given ibrav and celldms
!
USE kinds, ONLY : DP
USE cell_base, ONLY : tpiba, celldm
USE wannier_base, ONLY : wfg, nw, weight
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: b1(3), b2(3), b3(3)
INTEGER, INTENT(IN) :: ibrav
REAL(DP) :: tweight(6), t0, t1, t2, t3, t4, t5, t6
INTEGER :: twfg(6,3), kk
twfg(:,:) = 0
twfg(1,1)=1
twfg(1,2)=0
twfg(1,3)=0
twfg(2,1)=0
twfg(2,2)=1
twfg(2,3)=0
twfg(3,1)=0
twfg(3,2)=0
twfg(3,3)=1
SELECT CASE(ibrav)
CASE(1)
!
! Cubic P [sc]
!
nw = 3
!
!
CASE(2)
!
! Cubic F [fcc]
!
nw = 4
twfg(4,1)=-1
twfg(4,2)=-1
twfg(4,3)=-1
!
!
CASE(3)
!
! Cubic I [bcc]
!
nw = 6
twfg(4,1)=1
twfg(4,2)=1
twfg(4,3)=0
twfg(5,1)=0
twfg(5,2)=1
twfg(5,3)=1
twfg(6,1)=-1
twfg(6,2)=0
twfg(6,3)=1
!
!
CASE(4)
!
! Hexagonal and Trigonal P
!
nw = 4
twfg(4,1)=1
twfg(4,2)=-1
twfg(4,3)=0
!
!
CASE(5)
!
! Trigonal R
!
t0 = 1.D0/3.D0
!
IF ( celldm(4) .ge. t0 ) THEN
!
nw = 4
!
twfg(4,1)=1
twfg(4,2)=1
twfg(4,3)=1
!
ELSE
!
IF ( celldm(4) .gt. 0 ) THEN
!
nw = 6
!
twfg(4,1)=1
twfg(4,2)=1
twfg(4,3)=0
twfg(5,1)=0
twfg(5,2)=1
twfg(5,3)=1
twfg(6,1)=1
twfg(6,2)=0
twfg(6,3)=1
!
ELSE IF ( celldm(4) .eq. 0 ) THEN
!
nw = 3
!
ELSE
!
nw = 6
!
twfg(4,1)=1
twfg(4,2)=-1
twfg(4,3)=0
twfg(5,1)=0
twfg(5,2)=1
twfg(5,3)=-1
twfg(6,1)=-1
twfg(6,2)=0
twfg(6,3)=1
!
END IF
!
END IF
CASE(6)
!
! Tetragonal P [st]
!
nw = 3
!
!
CASE(7)
!
! Tetragonal I [bct]
!
nw = 6
twfg(4,1)=1
twfg(4,2)=0
twfg(4,3)=1
twfg(5,1)=0
twfg(5,2)=1
twfg(5,3)=-1
twfg(6,1)=1
twfg(6,2)=1
twfg(6,3)=0
!
!
CASE(8)
!
! Orthorhombic P
!
nw = 3
!
!
CASE(9)
!
! Orthorhombic C
!
IF (celldm(2).EQ.1) THEN ! Tetragonal P
!
nw=3
!
ELSE
!
nw = 4
!
IF ( celldm(2) < 1 ) THEN
!
twfg(4,1)=1
twfg(4,2)=-1
twfg(4,3)=0
!
ELSE
!
twfg(4,1)=1
twfg(4,2)=1
twfg(4,3)=0
!
END IF
!
END IF
!
!
CASE(10)
!
! Orthorhombic F
!
twfg(4,1)=1
twfg(4,2)=1
twfg(4,3)=1
!
IF ( celldm(2) .eq. 1 .AND. celldm(3) .eq. 1 ) THEN ! Cubic F
!
nw = 4
!
ELSE
!
nw = 6
!
IF ( celldm(2) .eq. 1 .AND. celldm(3) .ne. 1) THEN ! Tetragonal I
!
twfg(5,1)=1
twfg(5,2)=1
twfg(5,3)=0
twfg(6,1)=0
twfg(6,2)=1
twfg(6,3)=1
!
ELSE IF ( celldm(2) .ne. 1 .AND. celldm(3) .eq. 1) THEN ! Tetragonal I
!
twfg(5,1)=1
twfg(5,2)=1
twfg(5,3)=0
twfg(6,1)=1
twfg(6,2)=0
twfg(6,3)=1
!
ELSE IF ( celldm(2) .eq. celldm(3) ) THEN ! Tetragonal I
!
twfg(5,1)=0
twfg(5,2)=1
twfg(5,3)=1
twfg(6,1)=1
twfg(6,2)=0
twfg(6,3)=1
!
ELSE IF ( celldm(2) .gt. 1 .and. celldm(3) .gt. 1 ) THEN
!
twfg(5,1)=0
twfg(5,2)=1
twfg(5,3)=1
twfg(6,1)=1
twfg(6,2)=0
twfg(6,3)=1
!
ELSE IF ( celldm(2) .lt. celldm(3) ) THEN
!
twfg(5,1)=1
twfg(5,2)=1
twfg(5,3)=0
twfg(6,1)=1
twfg(6,2)=0
twfg(6,3)=1
!
ELSE
!
twfg(5,1)=1
twfg(5,2)=1
twfg(5,3)=0
twfg(6,1)=0
twfg(6,2)=1
twfg(6,3)=1
!
END IF
!
END IF
!
!
CASE(11)
!
! Orthorhombic I
!
nw = 6
!
twfg(4,1)=1
twfg(4,2)=1
twfg(4,3)=0
twfg(5,1)=0
twfg(5,2)=1
twfg(5,3)=1
twfg(6,1)=-1
twfg(6,2)=0
twfg(6,3)=1
!
!
CASE(12)
!
! Monoclinic P
!
IF ( celldm(4) .eq. 0 ) THEN ! Orthorhombic P
!
nw = 3
!
ELSE
!
nw = 4
!
t1 = SQRT(DOT_PRODUCT(b1,b1))
t2 = SQRT(DOT_PRODUCT(b2,b2))
t4 = DOT_PRODUCT(b1,b2)/t1/t2
!
t0 = - t4 * t1 / t2
kk = NINT(t0)
!
IF((kk.EQ.0).AND.(t0.GT.0)) kk=1
IF((kk.EQ.0).AND.(t0.LT.0)) kk=-1
twfg(4,1)=1
twfg(4,2)=kk
twfg(4,3)=0
!
END IF
!
!
CASE(0,13,14)
!
! Monoclinic C, Triclinic P, Free Cell
!
nw = 6
!
t1 = SQRT(DOT_PRODUCT(b1,b1))
t2 = SQRT(DOT_PRODUCT(b2,b2))
t3 = SQRT(DOT_PRODUCT(b3,b3))
t4 = DOT_PRODUCT(b1,b2)/t1/t2
t5 = DOT_PRODUCT(b2,b3)/t2/t3
t6 = DOT_PRODUCT(b3,b1)/t3/t1
!
t0 = - t4 * t1 / t2
kk = NINT(t0)
!
IF((kk.EQ.0).AND.(t0.GE.0)) kk=1
IF((kk.EQ.0).AND.(t0.LT.0)) kk=-1
twfg(4,1)=1
twfg(4,2)=kk
twfg(4,3)=0
!
t0 = - t5 * t2 / t3
kk = NINT(t0)
!
IF((kk.EQ.0).AND.(t0.GE.0)) kk=1
IF((kk.EQ.0).AND.(t0.LT.0)) kk=-1
!
twfg(5,1)=0
twfg(5,2)=1
twfg(5,3)=kk
!
t0 = - t6 * t3 / t1
kk = NINT(t0)
!
IF((kk.EQ.0).AND.(t0.GE.0)) kk=1
IF((kk.EQ.0).AND.(t0.LT.0)) kk=-1
!
twfg(6,1)=kk
twfg(6,2)=0
twfg(6,3)=1
!
!
END SELECT
!
CALL tric_wts2( b1, b2, b3, nw, twfg, tweight )
!
ALLOCATE(wfg(nw,3), weight(nw))
!
wfg(:,:) = twfg(1:nw,:)
weight(:) = tweight(1:nw)
!
RETURN
!
END SUBROUTINE setwfg
!
!----------------------------------------------------------------------------
SUBROUTINE tric_wts( rp1, rp2, rp3, alat, wts )
!----------------------------------------------------------------------------
!
! ... This subroutine computes the weights to be used for
! ... R.P. translations in the WF calculation in the case
! ... of ibrav=0 or ibrav=14
!
USE kinds, ONLY : DP
USE constants, ONLY : pi
USE cell_base, ONLY : tpiba, tpiba2
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rp1(3), rp2(3), rp3(3)
REAL(DP), INTENT(IN) :: alat
REAL(DP), INTENT(OUT) :: wts(6)
!
REAL(DP) :: b1x, b2x, b3x, b1y, b2y, b3y, b1z, b2z, b3z
INTEGER :: i
!
!
b1x = rp1(1)*tpiba
b2x = rp2(1)*tpiba
b3x = rp3(1)*tpiba
b1y = rp1(2)*tpiba
b2y = rp2(2)*tpiba
b3y = rp3(2)*tpiba
b1z = rp1(3)*tpiba
b2z = rp2(3)*tpiba
b3z = rp3(3)*tpiba
! WRITE( stdout, * ) 'COMPUTING WEIGHTS NOW ...'
wts(1) = tpiba2*(-b1z*b2x*b2z*b3x + b2y**2*b3x**2 + b1z*b2z*b3x**2 + &
b2z**2*b3x**2 - b1z*b2y*b2z*b3y - 2.D0*b2x*b2y*b3x*b3y + &
b2x**2*b3y**2 + b1z*b2z*b3y**2 + b2z**2*b3y**2 + &
b1z*b2x**2*b3z + b1z*b2y**2*b3z - b1z*b2x*b3x*b3z - &
2.D0*b2x*b2z*b3x*b3z - b1z*b2y*b3y*b3z - &
2.D0*b2y*b2z*b3y*b3z + b2x**2*b3z**2 + b2y**2*b3z**2 + &
b1x*(b2y**2*b3x + b2z**2*b3x - b2y*(b2x + b3x)*b3y - &
b2z*(b2x + b3x)*b3z + b2x*(b3y**2 + b3z**2)) + &
b1y*(b2x**2*b3y - b2x*b3x*(b2y + b3y) + &
b2z*b3y*(b2z - b3z) + b2y*(b3x**2 - b2z*b3z + b3z**2)))/ &
((b1z*b2y*b3x - b1y*b2z*b3x - b1z*b2x*b3y + b1x*b2z*b3y &
+ b1y*b2x*b3z - b1x*b2y*b3z)**2)
wts(2) = tpiba2*(b1z**2*(b2x*b3x + b3x**2 + b3y*(b2y + b3y)) + &
b1y**2*(b2x*b3x + b3x**2 + b3z*(b2z + b3z)) - &
b1z*(-b2z*(b3x**2 + b3y**2) + (b2x*b3x + b2y*b3y)*b3z + &
b1x*(b2z*b3x + (b2x + 2.D0* b3x)*b3z)) - &
b1y*(b1x*(b2y*b3x + (b2x + 2.D0*b3x)*b3y) + &
b3y*(b1z*b2z + b2x*b3x + 2.D0*b1z*b3z + b2z*b3z) - &
b2y*(b3x**2 - b1z* b3z + b3z**2)) + &
b1x*(-b2y*b3x*b3y + b2x*b3y**2 - b2z*b3x*b3z + b2x*b3z**2 + &
b1x*(b2y*b3y + b3y**2 + b3z*(b2z + b3z))))/ &
((b1z*b2y*b3x - b1y*b2z*b3x - b1z*b2x*b3y + b1x*b2z*b3y + &
b1y*b2x*b3z - b1x*b2y*b3z)**2)
wts(3) = tpiba2*(b1z**2*(b2x**2 + b2x*b3x + b2y*(b2y + b3y)) - &
b1y*(2.D0*b1z*b2y*b2z + b2x*b2y*b3x - b2x**2*b3y + &
b1z*b2z*b3y - b2z**2*b3y + b1x*(2.D0*b2x*b2y + b2y*b3x + b2x*b3y) + &
b1z*b2y*b3z + b2y*b2z*b3z) + b1y**2*(b2x**2 + b2x*b3x + b2z*(b2z + b3z)) - &
b1z*(b2x*b2z*b3x + b2y*b2z*b3y - b2x**2*b3z - b2y**2*b3z + &
b1x*(2.D0*b2x*b2z + b2z*b3x + b2x*b3z)) + &
b1x*(b2y**2*b3x + b2z**2*b3x - b2x*b2y*b3y - b2x*b2z*b3z + &
b1x*(b2y**2 + b2y*b3y + b2z*(b2z + b3z))))/ &
((b1z*b2y*b3x - b1y*b2z*b3x - b1z*b2x*b3y + b1x*b2z*b3y + b1y*b2x*b3z - &
b1x*b2y*b3z)**2)
wts(4) = tpiba2*(b1z*(-b2z*(b3x**2 + b3y**2) + (b2x*b3x + b2y*b3y)*b3z) + &
b1y*(b3y*(b2x*b3x + b2z*b3z) - b2y*(b3x**2 + b3z**2)) + &
b1x*(b2y*b3x*b3y + b2z*b3x*b3z - b2x*(b3y**2 + b3z**2)))/ &
((b1z*b2y*b3x - b1y*b2z*b3x - b1z*b2x*b3y + b1x*b2z*b3y + &
b1y*b2x*b3z - b1x*b2y*b3z)**2)
wts(5) = -tpiba2*(b1z**2*(b2x*b3x + b2y*b3y) - b1x*b1z*(b2z*b3x + b2x*b3z) - &
b1y*(b1x*b2y*b3x + b1x*b2x*b3y + b1z*b2z*b3y + b1z*b2y*b3z) + &
b1y**2*(b2x*b3x + b2z*b3z) + b1x**2*(b2y*b3y + b2z*b3z))/ &
((b1z*b2y*b3x - b1y*b2z*b3x - b1z*b2x*b3y + b1x*b2z*b3y + &
b1y*b2x*b3z - b1x*b2y*b3z)**2)
wts(6) = -tpiba2*(b1z*(-b2x*b2z*b3x - b2y*b2z*b3y + b2x**2*b3z + b2y**2*b3z) + &
b1x*(b2y**2*b3x + b2z**2*b3x - b2x*b2y*b3y - b2x*b2z*b3z) + &
b1y*(-b2x*b2y*b3x + b2x**2*b3y + b2z*(b2z*b3y - b2y*b3z)))/ &
((b1z*b2y*b3x - b1y*b2z*b3x - b1z*b2x*b3y + b1x*b2z*b3y + &
b1y*b2x*b3z - b1x*b2y*b3z)**2)
!
RETURN
!
END SUBROUTINE tric_wts
!
!----------------------------------------------------------------------------
SUBROUTINE tric_wts2( rp1, rp2, rp3, nw, wfg, weight )
!----------------------------------------------------------------------------
!
! ... added by Young-Su Lee ( Nov 2006 )
!
! Find the least square solutions of weights for G vectors
! If the set of G vectors and calculated weights do not conform to the condition,
! SUM_i weight_i G_ia G_ib = delta_ab
! the code stops.
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
!
IMPLICIT NONE
!
REAL(DP), INTENT(IN) :: rp1(3), rp2(3), rp3(3)
INTEGER, INTENT(IN) :: wfg(6,3), nw
REAL(DP), INTENT(OUT) :: weight(6)
!
REAL(DP) :: gp(6,nw), A(6,nw), gr(nw,3), S(6), R(6), WORK(1000), t
INTEGER :: i, LWORK, INFO
!
DO i=1, nw
gr(i,:) = wfg(i,1)*rp1(:)+wfg(i,2)*rp2(:)+wfg(i,3)*rp3(:)
END DO
DO i=1, nw
gp(1,i)=gr(i,1)*gr(i,1)
gp(2,i)=gr(i,2)*gr(i,2)
gp(3,i)=gr(i,3)*gr(i,3)
gp(4,i)=gr(i,1)*gr(i,2)
gp(5,i)=gr(i,2)*gr(i,3)
gp(6,i)=gr(i,3)*gr(i,1)
END DO
!
R = 0.D0
R(1:3) = 1.D0
!
LWORK=1000
A = gp
S = R
!
CALL DGELS( 'N', 6, nw, 1, A, 6, S, 6, WORK, LWORK, INFO )
!
IF (INFO .ne. 0) THEN
WRITE( stdout, * ) "failed to get a weight factor for ",INFO,"th vector"
STOP
END IF
!
weight(1:nw) = S(:)
S=matmul(gp,weight(1:nw))
!
DO i=1, nw
IF ( weight(i) .lt. 0.D0 ) THEN
WRITE( stdout, * ) "WARNING: weight factor less than zero"
END IF
END DO
!
DO i=1,6
t = abs(S(i)-R(i))
IF ( t .gt. 1.D-8 ) THEN
WRITE( stdout, * ) "G vectors do not satisfy the completeness condition",i,t
STOP
END IF
END DO
!
RETURN
!
END SUBROUTINE tric_wts2
!
!----------------------------------------------------------------------------
SUBROUTINE small_box_wf( i_1, j_1, k_1, nw1 )
!----------------------------------------------------------------------------
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE constants, ONLY : fpi
USE wannier_base, ONLY : expo
USE grid_dimensions, ONLY : nr1, nr2, nr3, nr1x, nr2x, nr3x, nnrx
USE fft_base, ONLY : dfftp
USE mp_global, ONLY : me_image
USE parallel_include
!
IMPLICIT NONE
INTEGER ir1, ir2, ir3, ibig3 , inw
REAL(DP) x
INTEGER , INTENT(in) :: nw1, i_1(nw1), j_1(nw1), k_1(nw1)
INTEGER :: me
me = me_image + 1
ALLOCATE(expo(nnrx,nw1))
DO inw=1,nw1
WRITE( stdout, * ) inw ,":", i_1(inw), j_1(inw), k_1(inw)
DO ir3=1,nr3
#ifdef __PARA
ibig3 = ir3 - dfftp%ipp( me )
IF(ibig3.GT.0.AND.ibig3.LE.dfftp%npp(me)) THEN
#else
ibig3=ir3
#endif
DO ir2=1,nr2
DO ir1=1,nr1
x = (((ir1-1)/DBLE(nr1x))*i_1(inw) + &
& ((ir2-1)/DBLE(nr2x))*j_1(inw) + &
& ((ir3-1)/DBLE(nr3x))*k_1(inw))*0.5d0*fpi
expo(ir1+(ir2-1)*nr1x+(ibig3-1)*nr1x*nr2x,inw) = CMPLX(COS(x), -SIN(x),kind=DP)
END DO
END DO
#ifdef __PARA
END IF
#endif
END DO
END DO
RETURN
END SUBROUTINE small_box_wf
!
!-----------------------------------------------------------------------
FUNCTION boxdotgridcplx(irb,qv,vr)
!-----------------------------------------------------------------------
!
! Calculate \sum_i qv(r_i)*vr(r_i) with r_i on box grid
! array qv(r) is defined on box grid, array vr(r)on dense grid
! irb : position of the box in the dense grid
! Parallel execution: remember to sum the contributions from other nodes
!
! use ion_parameters
!
USE kinds, ONLY : DP
USE grid_dimensions, ONLY : nnrx, nr1, nr2, nr3, nr1x, nr2x, nr3x
USE smallbox_grid_dimensions, ONLY : nnrbx, nr1b, nr2b, nr3b, &
nr1bx, nr2bx, nr3bx
USE fft_base, ONLY : dfftp
USE mp_global, ONLY : me_image
!
IMPLICIT NONE
!
INTEGER, INTENT(IN):: irb(3)
COMPLEX(DP), INTENT(IN):: qv(nnrbx), vr(nnrx)
COMPLEX(DP) :: boxdotgridcplx
!
INTEGER :: ir1, ir2, ir3, ir, ibig1, ibig2, ibig3, ibig, me
!
me = me_image + 1
!
boxdotgridcplx = ZERO
DO ir3=1,nr3b
ibig3=irb(3)+ir3-1
ibig3=1+MOD(ibig3-1,nr3)
#ifdef __PARA
ibig3 = ibig3 - dfftp%ipp( me )
IF (ibig3.GT.0.AND.ibig3.LE.dfftp%npp(me)) THEN
#endif
DO ir2=1,nr2b
ibig2=irb(2)+ir2-1
ibig2=1+MOD(ibig2-1,nr2)
DO ir1=1,nr1b
ibig1=irb(1)+ir1-1
ibig1=1+MOD(ibig1-1,nr1)
ibig=ibig1 + (ibig2-1)*nr1x + (ibig3-1)*nr1x*nr2x
ir =ir1 + (ir2-1)*nr1bx + (ir3-1)*nr1bx*nr2bx
boxdotgridcplx = boxdotgridcplx + qv(ir)*vr(ibig)
END DO
END DO
#ifdef __PARA
ENDIF
#endif
END DO
!
RETURN
!
END FUNCTION boxdotgridcplx
!
!----------------------------------------------------------------------------
SUBROUTINE write_rho_g( rhog )
!----------------------------------------------------------------------------
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE gvecp, ONLY : ngm
USE reciprocal_vectors, ONLY : gx, mill_l
USE electrons_base, ONLY : nspin
USE fft_base, ONLY : dfftp
USE mp_global, ONLY : nproc_image, me_image, root_image, intra_image_comm
USE mp, ONLY : mp_barrier, mp_gather, mp_set_displs
USE parallel_include
!
IMPLICIT NONE
!
COMPLEX(DP) ,INTENT(IN) :: rhog(ngm,nspin)
REAL(DP), ALLOCATABLE:: gnx(:,:), bigg(:,:)
COMPLEX(DP),ALLOCATABLE :: bigrho(:)
COMPLEX(DP) :: rhotmp_g(ngm)
INTEGER :: ntot, i, j, me
#ifdef __PARA
INTEGER proc, ierr, ngdens(nproc_image), displs(nproc_image)
#endif
CHARACTER (LEN=6) :: name
CHARACTER (LEN=15) :: name2
me = me_image + 1
ALLOCATE(gnx(3,ngm))
DO i=1,ngm
gnx(1,i)=gx(1,i)
gnx(2,i)=gx(2,i)
gnx(3,i)=gx(3,i)
END DO
#ifdef __PARA
DO i=1,nproc_image
ngdens(i)=(dfftp%ngl(i)+1)/2
END DO
CALL mp_set_displs( ngdens, displs, ntot, nproc_image )
IF(me.EQ.1) THEN
ALLOCATE(bigg(3,ntot))
END IF
CALL mp_barrier(intra_image_comm)
CALL mp_gather( gnx, bigg, ngdens, displs, root_image, intra_image_comm )
DO i=1,nspin
rhotmp_g(1:ngm)=rhog(1:ngm,i)
IF(me.EQ.1) THEN
ALLOCATE (bigrho(ntot))
END IF
CALL mp_barrier(intra_image_comm)
CALL mp_gather( rhotmp_g, bigrho, ngdens, displs, root_image, intra_image_comm )
IF(me.EQ.1) THEN
IF(i.EQ.1) name2="CH_DEN_G_PARA.1"
IF(i.EQ.2) name2="CH_DEN_G_PARA.2"
OPEN(unit=57, file=name2)
DO j=1,ntot
WRITE(57,*) bigrho(j)
END DO
CLOSE(57)
DEALLOCATE(bigrho)
END IF
WRITE( stdout, * ) "Charge density written to ", name2
END DO
IF(me.EQ.1) THEN
name="G_PARA"
OPEN(unit=56, file=name)
DO i=1,ntot
WRITE(56,*) bigg(:,i)
END DO
CLOSE(56)
DEALLOCATE(bigg)
END IF
WRITE( stdout, * ) "G-vectors written to G_PARA"
#else
ntot=ngm
ALLOCATE(bigg(3,ntot))
bigg(1:3,1:ntot)=gnx(1:3,1:ngm)
DO i=1,nspin
ALLOCATE(bigrho(ntot))
bigrho(1:ngm)=rhog(1:ngm,i)
IF(i.EQ.1) name2="CH_DEN_G_SERL.1"
IF(i.EQ.2) name2="CH_DEN_G_SERL.2"
OPEN(unit=57, file=name2)
DO j=1,ntot
WRITE(57,*) bigrho(j)
END DO
CLOSE(57)
DEALLOCATE(bigrho)
WRITE( stdout, * ) "Charge density written to", name2
END DO
name="G_SERL"
OPEN(unit=56, file=name)
DO i=1,ntot
WRITE(56,*) bigg(:,i)
END DO
CLOSE(56)
DEALLOCATE(bigg)
WRITE( stdout, * ) "G-vectors written to G_SERL"
#endif
!
DEALLOCATE(gnx)
!
RETURN
!
END SUBROUTINE write_rho_g
!
!----------------------------------------------------------------------------
SUBROUTINE macroscopic_average( rhog, tau0, e_tuned )
!----------------------------------------------------------------------------
!
USE kinds, ONLY : DP
USE reciprocal_vectors, ONLY : gx
USE gvecp, ONLY : ngm
USE electrons_base, ONLY : nspin
USE tune, ONLY : npts, xdir, ydir, zdir, B, &
shift, start, av0, av1
USE cell_base, ONLY : a1, a2, a3, tpiba, omega
USE ions_base, ONLY : nsp, na, zv, nax
USE constants, ONLY : pi, tpi
USE mp, ONLY : mp_barrier, mp_bcast, mp_gather, mp_set_displs
USE fft_base, ONLY : dfftp
USE mp_global, ONLY : nproc_image, me_image, root_image, intra_image_comm
USE parallel_include
!
IMPLICIT NONE
!
REAL(DP), ALLOCATABLE:: gnx(:,:), bigg(:,:)
COMPLEX(DP) ,INTENT(in) :: rhog(ngm,nspin)
COMPLEX(DP),ALLOCATABLE :: bigrho(:)
COMPLEX(DP), ALLOCATABLE :: rhotmp_g(:)
INTEGER ntot, i, j, ngz, l, isa
INTEGER ,ALLOCATABLE :: g_red(:,:)
#ifdef __PARA
INTEGER proc, ierr, ngdens(nproc_image), displs( nproc_image )
#endif
REAL(DP) zlen,vtot, pos(3,nax,nsp), a_direct(3,3),a_trans(3,3), e_slp, e_int
REAL(DP), INTENT(out) :: e_tuned(3)
REAL(DP), INTENT(in) :: tau0(3,nax)
REAL(DP),ALLOCATABLE :: v_mr(:), dz(:), gz(:), g_1(:,:), vbar(:), cd(:), v_final(:)
REAL(DP), ALLOCATABLE:: cdion(:), cdel(:), v_line(:), dist(:)
COMPLEX(DP),ALLOCATABLE :: rho_ion(:),v_1(:),vmac(:),rho_tot(:),rhogz(:), bigrhog(:)
INTEGER :: me
me = me_image + 1
ALLOCATE(gnx(3,ngm))
DO i=1,ngm
gnx(1,i)=gx(1,i)
gnx(2,i)=gx(2,i)
gnx(3,i)=gx(3,i)
END DO
#ifdef __PARA
DO i=1,nproc_image
ngdens(i)=(dfftp%ngl(i)+1)/2
END DO
CALL mp_set_displs( ngdens, displs, ntot, nproc_image )
#else
ntot=ngm
#endif
ALLOCATE(bigg(3,ntot))
ALLOCATE (bigrho(ntot))
ALLOCATE (bigrhog(2*ntot-1))
#ifdef __PARA
CALL mp_barrier( intra_image_comm )
!
CALL mp_gather( gnx, bigg, ngdens, displs, root_image,intra_image_comm )
!
CALL mp_bcast( bigg, root_image, intra_image_comm )
!
ALLOCATE( rhotmp_g( ngm ) )
rhotmp_g(1:ngm)=rhog(1:ngm,1)
CALL mp_barrier( intra_image_comm )
!
CALL mp_gather( rhotmp_g, bigrho, ngdens, displs, root_image,intra_image_comm )
!
DEALLOCATE( rhotmp_g )
!
CALL mp_bcast( bigrho, root_image, intra_image_comm )
!
#else
!
bigg(1:3,1:ntot)=gnx(1:3,1:ngm)
bigrho(1:ngm)=rhog(1:ngm,1)
!
#endif
ALLOCATE(g_1(3,2*ntot-1))
ALLOCATE(g_red(3,2*ntot-1))
ALLOCATE(v_mr(npts))
ALLOCATE(v_final(npts))
ALLOCATE(dz(npts))
ALLOCATE(vbar(npts))
ALLOCATE(cd(npts))
ALLOCATE(cdel(npts))
ALLOCATE(cdion(npts))
!-- needed for non-orthogonal cells
a_direct(1,1:3)=a1(1:3)
a_direct(2,1:3)=a2(1:3)
a_direct(3,1:3)=a3(1:3)
a_trans=TRANSPOSE(a_direct)
!--- Construct rho(-g) from rho(g). rgo(-g)=rho*(g)
bigrhog(1:ntot)=bigrho(1:ntot)
g_1(:,1:ntot)=bigg(:,1:ntot)
DO i=2,ntot
bigrhog(ntot+i-1)=CONJG(bigrho(i))
g_1(:,ntot+i-1)=-bigg(:,i)
END DO
!--- needed fot non-orthogonal cells
DO i=1,2*ntot-1
g_red(:,i)=NINT(MATMUL(a_trans(:,:),g_1(:,i))*tpiba/tpi)
END DO
!--- define the direction of the line
xdir=1
ydir=2
IF ((zdir).EQ.1) xdir=3
IF ((zdir).EQ.2) ydir=3
IF(zdir.EQ.1) zlen=DSQRT(a1(1)**2+a1(2)**2+a1(3)**2)
IF(zdir.EQ.2) zlen=DSQRT(a2(1)**2+a2(2)**2+a2(3)**2)
IF(zdir.EQ.3) zlen=DSQRT(a3(1)**2+a3(2)**2+a3(3)**2)
!--- We need the potentiail only along zdir, so pick the appropriate G-vectors with Gxdir=Gydir=0
ngz=0
DO i=1,2*ntot-1
IF((g_red(xdir,i).EQ.0).AND.(g_red(ydir,i).EQ.0)) ngz=ngz+1
END DO
ALLOCATE(gz(ngz))
ALLOCATE(rhogz(ngz))
ALLOCATE(rho_ion(ngz))
ALLOCATE(rho_tot(ngz))
ALLOCATE(vmac(ngz))
ALLOCATE(v_1(ngz))
!--- The G-vectors are output in units of 2*pi/a, so convert them to the correct values
j=0
DO i=1,2*ntot-1
IF((g_red(xdir,i).EQ.0).AND.(g_red(ydir,i).EQ.0)) THEN
j=j+1
gz(j)=g_1(zdir,i)*tpiba
rhogz(j)=bigrhog(i)
END IF
END DO
isa = 0
DO i=1,nsp
DO j=1,na(i)
isa = isa + 1
pos(:,j,i)=tau0(:,isa)
END DO
END DO
!--- Construct the ionic Charge density in G-space
rho_ion = ZERO
!
DO j=1,ngz
DO i=1,nsp
DO l=1,na(i)
rho_ion(j)=rho_ion(j)+zv(i)*EXP(-CI*gz(j)*pos(zdir,l,i))*EXP(-gz(j)**2/(4.D0*ONE))
END DO
END DO
END DO
rho_ion=rho_ion/omega
!--- Construct the total Charge density in G-space
rho_tot=rho_ion-rhogz
!--- Construct the electrostatic potential and macroscopic average in G-space
v_1(1)=ZERO
vmac(1)=ZERO
v_1(2:ngz)=4*pi*rho_tot(2:ngz)/gz(2:ngz)**2
vmac(2:)=v_1(2:)*SIN(gz(2:)*b)/(gz(2:)*b)
!--- Calculate planewise average in R-space and FFT V(Gz) ---> V(z) ... well not really FFT but FT
vbar=0.D0
v_mr=0.D0
cdel=0.D0
cdion=0.D0
cd=0.D0
DO j=1,npts
dz(j)=(j-1)*zlen/(npts*1.D0)
DO i=1,ngz
vbar(j)=vbar(j)-DBLE(EXP(CI*gz(i)*dz(j))*v_1(i))
v_mr(j)=v_mr(j)-DBLE(EXP(CI*gz(i)*dz(j))*vmac(i))
cdel(j)=cdel(j)-DBLE(EXP(CI*gz(i)*dz(j))*rhogz(i))
cdion(j)=cdion(j)+DBLE(EXP(CI*gz(i)*dz(j))*rho_ion(i))
cd(j)=cd(j)+DBLE(EXP(CI*gz(i)*dz(j))*rho_tot(i))
END DO
! WRITE( stdout, * ) vbar(j), v_mr(j), cdel(j), cdion(j)
END DO
IF (shift) THEN
vtot=(v_mr(start)+v_mr(start-1))/2.D0
v_final(1:npts-start+1)=v_mr(start:npts)-vtot
v_final(npts-start+2:npts)=v_mr(1:start-1)-vtot
ELSE
vtot=(v_mr(1)+v_mr(npts))/2.D0
v_final(1:npts)=v_mr(1:npts)-vtot
END IF
e_tuned=0.D0
ALLOCATE(v_line(1:av1-av0+1))
ALLOCATE(dist(1:av1-av0+1))
v_line(1:av1-av0+1)=v_final(av0:av1)
dist(1:av1-av0+1) =dz(av0:av1)
e_tuned(zdir)=-(v_final(av1)-v_final(av0))/((av1-av0)*zlen/(npts*1.D0))
DEALLOCATE(bigg,g_1,bigrho,bigrhog,g_red)
DEALLOCATE(gnx,v_mr,v_final,dz,vbar,cd,cdel,cdion)
DEALLOCATE(v_line, dist)
DEALLOCATE(gz,rhogz,rho_ion,rho_tot,vmac,v_1)
RETURN
END SUBROUTINE macroscopic_average
!
!----------------------------------------------------------------------------
SUBROUTINE least_square( npts, x, y, slope, intercept )
!----------------------------------------------------------------------------
!
USE kinds, ONLY : DP
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: npts
REAL(DP), INTENT(IN) :: x(npts), y(npts)
REAL(DP), INTENT(OUT):: slope, intercept
!
INTEGER :: i
REAL(DP) :: sumx,sumy,sumx2,sumxy,sumsqx
REAL(DP) :: xav,yav
sumxy=0.D0
sumx =0.D0
sumy =0.D0
sumx2=0.D0
DO i=1,npts
sumxy=sumxy+x(i)*y(i)
sumx =sumx +x(i)
sumy =sumy +y(i)
sumx2=sumx2+x(i)*x(i)
END DO
sumsqx=sumx**2
xav=sumx/DBLE(npts)
yav=sumy/DBLE(npts)
slope=(npts*sumxy - sumx*sumy)/(npts*sumx2 - sumsqx)
intercept=yav-slope*xav
RETURN
END SUBROUTINE least_square
!
!----------------------------------------------------------------------------
SUBROUTINE wfsteep( m, Omat, Umat, b1, b2, b3 )
!----------------------------------------------------------------------------
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE wannier_base, ONLY : nw, weight, nit, tolw, wfdt, maxwfdt, nsd
USE control_flags, ONLY : iprsta
USE cell_base, ONLY : alat
USE constants, ONLY : tpi, autoaf => BOHR_RADIUS_ANGS
USE smooth_grid_dimensions, ONLY : nr1s, nr2s, nr3s
USE mp_global, ONLY : me_image
USE printout_base, ONLY : printout_base_open, printout_base_unit, &
printout_base_close
USE parallel_include
!
IMPLICIT NONE
! (m,m) is the size of the matrix Ospin.
! Ospin is input overlap matrix.
! Uspin is the output unitary transformation.
! Rough guess for Uspin can be carried in.
!
! conjugated gradient to search maximization
!
INTEGER, INTENT(in) :: m
REAL(DP), INTENT(in) :: b1(3),b2(3),b3(3)
COMPLEX(DP), INTENT(inout) :: Omat(nw, m, m)
REAL(DP), INTENT(inout) :: Umat(m,m)
!
INTEGER :: i, j, k, l, ig, ierr, ti, tj, tk, inw, ir, adjust
INTEGER :: f3(nw), f4(nw), ierr1
REAL(DP) :: slope, slope2, t1, t2, t3, mt(nw),t21,temp1,maxdt
REAL(DP) :: U(m,m), wfc(3, m), Wm(m,m), schd(m,m), f2(4*m), gr(nw, 3)
REAL(DP) :: Uspin2(m,m),temp2,wfdtold,oldt1,t01, d3(m,m), d4(m,m), U1(m,m)
REAL(DP) :: spread, sp
REAL(DP), ALLOCATABLE :: wr(:)
REAL(DP), ALLOCATABLE :: W(:,:)
COMPLEX(DP) :: ct1, ct2, ct3, z(m, m), X(m, m), d(m,m), d2(m,m)
COMPLEX(DP) :: f1(2*m-1), wp(m*(m+1)/2), Oc(nw, m, m)
COMPLEX(DP) :: Oc2(nw, m, m),wp1(m*(m+1)/2), X1(m,m), U2(m,m), U3(m,m)
INTEGER :: me, iunit
!
me = me_image + 1
!
ALLOCATE(W(m,m), wr(m))
!
Umat=0.D0
DO i=1,m
Umat(i,i)=1.D0
END DO
Oc=ZERO
Oc2=ZERO
X1=ZERO
U2=Umat*ONE
!
! update Oc using the initial guess of Uspin
!
DO inw=1, nw
X1(:, :)=Omat(inw, :, :)
U3=ZERO
CALL zgemm ('T', 'N', m,m,m,ONE,U2,m,X1,m,ZERO,U3,m)
X1=ZERO
CALL zgemm ('N','N', m,m,m,ONE,U3,m,U2,m,ZERO,X1,m)
Oc(inw, :, :)=X1(:, :)
END DO
U2=ZERO
U3=ZERO
W=0.D0
schd=0.D0
oldt1=0.D0
wfdtold=0.D0
DO k=1, nit
t01=0.D0 !use t1 to store the value of omiga
DO inw=1, nw
DO i=1, m
t01=t01+DBLE(CONJG(Oc(inw, i, i))*Oc(inw, i, i))
END DO
END DO
! WRITE( stdout, * ) t01
IF(ABS(oldt1-t01).LT.tolw) THEN
IF(me.EQ.1) THEN
WRITE(27,*) "MLWF Generated at Step",k
END IF
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "MLWF Generated at Step",k
END IF
GO TO 40
END IF
! oldt1=t01
! calculate d(omiga)/dW and store result in W
! W should be a real symmetric matrix for gamma-point calculation
!
Wm=W
W=0.D0
DO inw=1, nw
t2=weight(inw)
DO i=1,m
DO j=i+1,m
W(i,j)=W(i,j)+t2*DBLE(Oc(inw,i,j)*CONJG(Oc(inw,i,i) &
-Oc(inw,j,j))+CONJG(Oc(inw,j,i))*(Oc(inw,i,i)-Oc(inw,j,j)))
END DO
END DO
END DO
W=W-TRANSPOSE(W)
! calculate slope=d(omiga)/d(lamda)
slope=SUM(W**2)
! calculate slope2=d2(omiga)/d(lamda)2
slope2=0.D0
DO ti=1, m
DO tj=1, m
DO tk=1, m
t2=0.D0
DO inw=1, nw
t2=t2+DBLE(Oc(inw,tj,tk)*CONJG(Oc(inw,tj,tj)+Oc(inw,tk,tk) &
-2.D0*Oc(inw,ti,ti))-4.D0*Oc(inw,ti,tk) &
*CONJG(Oc(inw,ti,tj)))*weight(inw)
END DO
slope2=slope2+W(tk,ti)*W(ti,tj)*2.D0*t2
END DO
END DO
END DO
slope2=2.D0*slope2
! use parabola approximation. Defined by 1 point and 2 slopes
IF (slope2.LT.0) wfdt=-slope/2.D0/slope2
IF (maxwfdt.GT.0.AND.wfdt.GT.maxwfdt) wfdt=maxwfdt
IF (k.LT.nsd) THEN
schd=W !use steepest-descent technique
! calculate slope=d(omiga)/d(lamda)
slope=SUM(schd**2)
! schd=schd*maxwfdt
DO i=1, m
DO j=i, m
wp1(i + (j-1)*j/2) = CMPLX(0.d0, schd(i,j),kind=DP)
END DO
END DO
#if defined (__ESSL)
!
CALL zhpev(21, wp1, wr, z, m, m, f2, 4*m)
!
ierr1 = 0
!
#else
!
CALL zhpev('V','U',m,wp1,wr,z,m,f1,f2,ierr)
!
#endif
IF (ierr.NE.0) STOP 'failed to diagonalize W!'
ELSE
!
CALL dgemm ('T','N', m,m,m,ONE,Wm,m,Wm,m,ZERO,d3,m)
t1=0.D0
DO i=1, m
t1=t1+d3(i, i)
END DO
IF (t1.NE.0) THEN
d4=(W-Wm)
CALL dgemm ('T','N', m,m,m,ONE,W,m,d4,m,ZERO,d3,m)
t2=0.D0
DO i=1, m
t2=t2+d3(i, i)
END DO
t3=t2/t1
schd=W+schd*t3
ELSE
schd=W
END IF
!
! calculate the new d(Lambda) for the new Search Direction
! added by Manu. September 19, 2001
!
! calculate slope=d(omiga)/d(lamda)
slope=SUM(schd**2)
!------------------------------------------------------------------------
! schd=schd*maxwfdt
DO i=1, m
DO j=i, m
wp1(i + (j-1)*j/2) = CMPLX(0.d0, schd(i,j),kind=DP)
END DO
END DO
#if defined __ESSL
CALL zhpev(21, wp1, wr, z, m, m, f2, 4*m)
ierr1 = 0
#else
CALL zhpev('V','U',m,wp1,wr,z,m,f1,f2,ierr)
#endif
IF (ierr.NE.0) STOP 'failed to diagonalize W!'
maxdt=maxwfdt
11 d=0.D0
DO i=1, m
d(i, i)=EXP(CI*(maxwfdt)*wr(i))
END DO
U3=ZERO
CALL zgemm ('N', 'N', m,m,m,ONE,z,m,d,m,ZERO,U3,m)
U2=ZERO
CALL zgemm ('N','C', m,m,m,ONE,U3,m,z,m,ZERO,U2,m)
U=DBLE(U2)
U2=ZERO
U3=ZERO
!
! update Uspin
U1=ZERO
CALL dgemm ('N', 'N', m,m,m,ONE,Umat,m,U,m,ZERO,U1,m)
Umat=U1
!
! update Oc
!
U2=Umat*ONE
U3=ZERO
DO inw=1, nw
X1(:,:)=Omat(inw,:,:)
CALL zgemm ('T', 'N', m,m,m,ONE,U2,m,X1,m,ZERO,U3,m)
X1=ZERO
CALL zgemm ('N','N',m,m,m,ONE,U3,m,U2,m,ZERO,X1,m)
Oc2(inw, :,:)=X(:,:)
END DO
U2=ZERO
U3=ZERO
!
t21=0.D0 !use t21 to store the value of omiga
DO inw=1, nw
DO i=1, m
t21=t21+DBLE(CONJG(Oc2(inw, i, i))*Oc2(inw, i, i))
END DO
END DO
temp1=-((t01-t21)+slope*maxwfdt)/(maxwfdt**2)
temp2=slope
wfdt=-temp2/(2*temp1)
IF (wfdt.GT.maxwfdt.OR.wfdt.LT.0.D0) THEN
maxwfdt=2*maxwfdt
GO TO 11
END IF
maxwfdt=maxdt
!
!
! use parabola approximation. Defined by 2 point and 1 slopes
! if (slope2.lt.0) wfdt=-slope/2.D0/slope2
! if (maxwfdt.gt.0.and.wfdt.gt.maxwfdt) wfdt=maxwfdt
!
! write(6, '(e12.5E2,1x,e11.5E2,1x,f6.2)') slope2, slope, wfdt
!-------------------------------------------------------------------------
!
! schd is the new searching direction
!
END IF
d=0.D0
DO i=1, m
d(i, i)=EXP(CI*wfdt*wr(i))
END DO !d=exp(d)
! U=z*exp(d)*z+
!
U3=ZERO
CALL zgemm ('N', 'N', m,m,m,ONE,z,m,d,m,ZERO,U3,m)
U2=ZERO
CALL zgemm ('N','C', m,m,m,ONE,U3,m,z,m,ZERO,U2,m)
U=DBLE(U2)
U2=ZERO
U3=ZERO
! update Uspin
!
U1=ZERO
CALL dgemm ('N', 'N', m,m,m,ONE,Umat,m,U,m,ZERO,U1,m)
Umat=U1
! update Oc
!
U2=Umat*ONE
U3=ZERO
DO inw=1, nw
X1(:, :)=Omat(inw, :, :)
CALL zgemm ('T', 'N', m,m,m,ONE,U2,m,X1,m,ZERO,U3,m)
X1=ZERO
CALL zgemm ('N','N',m,m,m,ONE,U3,m,U2,m,ZERO,X1,m)
Oc(inw, :, :)=X1(:, :)
END DO
U2=ZERO
U3=ZERO
IF(ABS(t01-oldt1).GE.tolw.AND.k.GE.nit) THEN
IF(me.EQ.1) THEN
WRITE(27,*) "MLWF Not generated after",k,"Steps."
END IF
IF(iprsta.GT.4) THEN
WRITE( stdout, * ) "MLWF Not generated after",k,"Steps."
END IF
GO TO 40
END IF
oldt1=t01
END DO
40 DEALLOCATE(W, wr)
!
! calculate the spread
!
! write(24, *) "spread: (unit \AA^2)"
IF(me.EQ.1) THEN
iunit = printout_base_unit( "spr" )
CALL printout_base_open( "spr" )
END IF
DO i=1, m
!
mt=1.D0-DBLE(Oc(:,i,i)*CONJG(Oc(:,i,i)))
sp = (alat*autoaf/tpi)**2*SUM(mt*weight)
!
IF(me.EQ.1) THEN
WRITE(iunit, '(f10.7)') sp
END IF
IF( sp < 0.D0 ) &
CALL errore( 'cp-wf', 'Something wrong WF Spread negative', 1 )
!
spread=spread+sp
!
END DO
spread=spread/DBLE(m)
IF(me.EQ.1) THEN
CALL printout_base_open( "spr" )
END IF
IF(me.EQ.1) THEN
WRITE(24, '(f10.7)') spread
WRITE(27,*) "Average spread = ", spread
END IF
!
Omat=Oc
!
RETURN
END SUBROUTINE wfsteep
!
!
!
!----------------------------------------------------------------------------
SUBROUTINE write_psi( c, jw )
!----------------------------------------------------------------------------
! ... for calwf 5 - M.S
! ... collect wavefunctions on first node and write to file
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout, ionode
USE gvecw , ONLY : ngw
USE electrons_base, ONLY : nbspx
USE mp, ONLY : mp_barrier, mp_set_displs, mp_gather
USE fft_base, ONLY : dfftp
USE mp_global, ONLY : nproc_image, me_image, root_image, intra_image_comm
!
IMPLICIT NONE
!
INTEGER :: jw
COMPLEX(DP) :: c(ngw,nbspx)
!
INTEGER ::i, ig, proc, ntot, ngpwpp(nproc_image)
INTEGER ::displs(nproc_image)
COMPLEX(DP), ALLOCATABLE:: psitot(:)
#if defined (__PARA)
!
DO proc=1,nproc_image
ngpwpp(proc)=(dfftp%nwl(proc)+1)/2
END DO
!
CALL mp_set_displs( ngpwpp, displs, ntot, nproc_image )
!
! allocate the needed work spaces
!
IF ( me_image == root_image ) THEN
ALLOCATE(psitot(ntot))
ELSE
ALLOCATE(psitot(1))
END IF
!
! ... gather all psis arrays on the first node, in psitot
!
CALL mp_barrier( intra_image_comm )
!
CALL mp_gather( c(:,jw), psitot, ngpwpp, displs, root_image, intra_image_comm )
!
! write the node-number-independent array
!
IF( me_image == root_image ) THEN
DO i=1,ntot
WRITE(22,*) psitot(i)
END DO
END IF
!
DEALLOCATE(psitot)
#else
!
DO i=1,ngw
WRITE(22,*) c(i,jw)
END DO
!
#endif
IF( ionode ) WRITE( stdout, * ) "State Written", jw
!
CALL stop_run( .TRUE. )
!
RETURN
!
END SUBROUTINE write_psi
!
!----------------------------------------------------------------------------
SUBROUTINE jacobi_rotation( m, Omat, Umat, b1, b2, b3 )
!----------------------------------------------------------------------------
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE wannier_base, ONLY : nw, weight, nit, tolw, wfdt, maxwfdt, nsd
USE control_flags, ONLY : iprsta
USE cell_base, ONLY : alat
USE constants, ONLY : tpi
USE smooth_grid_dimensions, ONLY : nr1s, nr2s, nr3s
USE mp_global, ONLY : me_image
USE printout_base, ONLY : printout_base_open, printout_base_unit, &
printout_base_close
USE parallel_include
!
IMPLICIT NONE
! (m,m) is the size of the matrix Ospin.
! Ospin is input overlap matrix.
! Uspin is the output unitary transformation.
!
! Jacobi rotations method is used to minimize the spread.
! (F. Gygi, J.-L. Fatterbert and E. Schwegler, Comput. Phys. Commun. 155, 1 (2003))
!
! This subroutine has been written by Sylvie Stucki and Audrius Alkauskas
! in the Chair of Atomic Scale Simulation in Lausanne (Switzerland)
! under the direction of Prof. Alfredo Pasquarello.
!
REAL(DP), PARAMETER :: autoaf=0.529177d0
INTEGER, intent(in) :: m
COMPLEX(DP), DIMENSION(nw, m, m), intent(inout) :: Omat
REAL(DP), DIMENSION(m, m), intent(inout) :: Umat
LOGICAL :: stopCriteria
INTEGER :: iterationNumber, lig, col, i, nbMat
INTEGER, PARAMETER :: dimG=2
REAL(DP), DIMENSION(2*nw, m, m):: OmatReal
REAL(DP), DIMENSION(dimG, dimG):: matrixG
REAL(DP), DIMENSION(dimG) :: eigenVec
REAL(DP) :: a1, a2 ! are the components aii-ajj and aij-aji of the matrixes used to build matrixG
REAL(DP) :: r, c, s ! For a single rotation
REAL(DP) :: bMinusa, outDiag ! To compute the eigenvector linked to the largest eigenvalue of matrixG
REAL(DP) :: newMat_ll, newMat_cc, newMat_lc, presentSpread, saveSpread, mt(nw)
REAL(DP), DIMENSION (m,2) :: newMat_cols
REAL(DP), INTENT(in) :: b1(3),b2(3),b3(3)
INTEGER :: me, iunit
REAL(DP), DIMENSION(m, m) :: matriceTest
!
me = me_image + 1
nbMat=2*nw
!
WRITE(24, *) 'Spreads before optimization'
DO i=1, m
!
mt=1.D0-DBLE(Omat(:,i,i)*CONJG(Omat(:,i,i)))
presentSpread = SUM(mt*weight)
presentSpread = (alat/tpi)*DSQRT(presentSpread)
WRITE(24, *) 'Spread of the ', i, '-th wannier function is ' , presentSpread
IF( presentSpread < 0.D0 ) &
CALL errore( 'cp-wf', 'Something is wrong, WannierF spread negative', 1 )
!
ENDDO
!
Umat=0.D0
DO i=1,m
Umat(i,i)=1.D0
END DO
do i=1,m
write (*, *) Umat(i, :)
end do
do i = 1, nw
OmatReal((2*i-1), :, :) = real(Omat(i, :, :), DP)
OmatReal(2*i, :, :) = aimag(Omat(i, :, :))
end do
!
iterationNumber = 0
stopCriteria = .false.
!
! Calculation of the spread
presentSpread = 0.
do i=1, nbMat
do lig=1, m-1
do col = lig+1, m
presentSpread = presentSpread + OmatReal(i, lig, col)*OmatReal(i, lig, col)
end do
end do
end do
print *, "Initial spread : ", presentSpread
saveSpread=presentSpread
!
! ATTENTION! limite d'iteration = nit !!!!
do while ((.not. stopCriteria) .and. (iterationNumber<nit))
iterationNumber=iterationNumber + 1
print *, "Tournus numero : ", iterationNumber
do lig = 1, m-1
do col =lig+1, m
matrixG(1,1) = 0.d0
matrixG(1,2) = 0.d0
matrixG(2,1) = 0.d0
matrixG(2,2) = 0.d0
!
!Building matrix G
!
do i= 1, nbMat
a1 = OmatReal(i, lig, lig)-OmatReal(i, col, col)
a2 = OmatReal(i, lig, col)+OmatReal(i, col, lig)
!print *, "a1 and a2 :", a1, a2
matrixG(1,1) = matrixG(1,1) + a1*a1
matrixG(1,2) = matrixG(1,2) + a1*a2
matrixG(2,1) = matrixG(2,1) + a2*a1
matrixG(2,2) = matrixG(2,2) + a2*a2
end do
!
! Computation of the eigenvector associated with the largest eigenvalue of matrixG
bMinusa = matrixG(2,2)-matrixG(1,1)
outDiag = matrixG(1,2)
!
if (abs(outDiag) .gt. 1d-10) then
eigenVec(1) = 1.d0
eigenVec(2) = (bMinusa + sqrt(bMinusa*bMinusa + &
4.d0*outDiag*outDiag))/(2.d0*outDiag)
else
if (bMinusa .lt. 0) then
eigenVec(1)=1.d0
eigenVec(2)=0.d0
else
eigenVec(1)=0.d0
eigenVec(2)=1.d0
end if
end if
!
r = sqrt(eigenVec(1)*eigenVec(1) + eigenVec(2)*eigenVec(2))
c = sqrt((eigenVec(1)+r)/(2.d0*r))
s = eigenVec(2)/sqrt(2.d0*r*(eigenVec(1)+r))
!
!Update of the matrixes
!
do i= 1, nbMat
! Computation of the new components
newMat_ll = c*c*OmatReal(i, lig, lig) +s*s*OmatReal(i, col, col) &
+ 2*s*c*OmatReal(i, lig, col)
newMat_cc = s*s*OmatReal(i, lig, lig) +c*c*OmatReal(i, col, col) &
- 2*s*c*OmatReal(i, lig, col)
!
newMat_lc = s*c* (-OmatReal(i, lig, lig) + OmatReal(i, col, col))&
+ (c*c-s*s) * OmatReal(i, lig, col)
newMat_cols(:, 1) = c*OmatReal(i, :, lig) + s*OmatReal(i, :, col)
newMat_cols(:, 2) = -s*OmatReal(i, :, lig) + c*OmatReal(i, :, col)
!
! copy of the components
!
OmatReal(i, :, lig) = newMat_cols(:,1)
OmatReal(i, :, col) = newMat_cols(:,2)
OmatReal(i, lig, :) = newMat_cols(:,1)
OmatReal(i, col, :) = newMat_cols(:,2)
!
OmatReal(i, lig, col) = newMat_lc
OmatReal(i, col, lig) = newMat_lc
OmatReal(i, lig, lig) = newMat_ll
OmatReal(i, col, col) = newMat_cc
end do
!
! Update of the matrix of base transformation
! We reuse newMat_cols to keep the new values before the copy
newMat_cols(:, 1) = c*Umat(:, lig) + s*Umat(:, col)
newMat_cols(:, 2) = -s*Umat(:, lig) + c*Umat(:, col)
!
Umat(:, lig) = newMat_cols(:, 1)
Umat(:, col) = newMat_cols(:, 2)
end do
end do
!matriceTest = matmul(Umat, transpose(Umat))
!write (*, *) matriceTest
!
! Calculation of the new spread
!
presentSpread = 0.d0
!
do i=1, nbMat
do lig=1, m-1
do col = lig+1, m
presentSpread = presentSpread + OmatReal(i, lig, col)*OmatReal(i, lig, col)
end do
end do
end do
!
print *, iterationNumber, presentSpread
!
if (saveSpread-presentSpread < tolw) then
print *, "Arret : ", iterationNumber, presentSpread
stopCriteria = .true.
end if
saveSpread = presentSpread
enddo
!
do i=1, nw
!
Omat(i, :, :) = OmatReal((2*i-1), :, :) + CI*OmatReal(2*i, :, :)
!
end do
!
WRITE(24, *) 'Spreads after optimization'
DO i=1, m
!
mt=1.D0-DBLE(Omat(:,i,i)*CONJG(Omat(:,i,i)))
presentSpread = SUM(mt*weight)
presentSpread = (alat/tpi)*DSQRT(presentSpread)
WRITE(24, *) 'Spread of the ', i, '-th wannier function is ' , presentSpread
IF( presentSpread < 0.D0 ) &
CALL errore( 'cp-wf', 'Something is wrong, WannierF spread negative', 1 )
!
ENDDO
RETURN
END SUBROUTINE jacobi_rotation