TABLE OF CONTENTS


abinit/prep_nonlop [ Functions ]

[ Top ] [ abinit ] [ Functions ]

NAME

 prep_nonlop

FUNCTION

 this routine prepares the data to the call of nonlop.

COPYRIGHT

 Copyright (C) 1998-2018 ABINIT group (FB,MT,GZ,MD,FDahm)
 this file is distributed under the terms of the
 gnu general public license, see ~abinit/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .
 for the initials of contributors, see ~abinit/doc/developers/contributors.txt .

INPUTS

  choice: chooses possible output:
    choice=1 => a non-local energy contribution
          =2 => a gradient with respect to atomic position(s)
          =3 => a gradient with respect to strain(s)
          =23=> a gradient with respect to atm. pos. and strain(s)
          =4 => a 2nd derivative with respect to atomic pos.
          =24=> a gradient and 2nd derivative with respect to atomic pos.
          =5 => a gradient with respect to k wavevector
          =6 => 2nd derivatives with respect to strain and atm. pos.
          =7 => no operator, just projections
  blocksize= size of block for FFT
  cpopt=flag defining the status of cwaveprj=<Proj_i|Cnk> scalars (see below, side effects)
  cwavef(2,npw*my_nspinor*blocksize)=planewave coefficients of wavefunction.
  gvnlc=matrix elements <G|Vnonlocal|C>
  hamk <type(gs_hamiltonian_type)>=data defining the Hamiltonian at a given k (NL part involved here)
  idir=direction of the - atom to be moved in the case (choice=2,signs=2),
                        - k point direction in the case (choice=5,signs=2)
                        - strain component (1:6) in the case (choice=2,signs=2) or (choice=6,signs=1)
  lambdablock(blocksize)=factor to be used when computing (Vln-lambda.S) - only for paw_opt=2
  mpi_enreg=informations about mpi parallelization
  nnlout=dimension of enlout (when signs=1):
  ntypat=number of types of atoms in cell
  paw_opt= define the nonlocal operator concerned with
  signs= if 1, get contracted elements (energy, forces, stress, ...)
         if 2, applies the non-local operator to a function in reciprocal space
  tim_nonlop=timing code of the calling routine (can be set to 0 if not attributed)

OUTPUT

  ==== if (signs==1) ====
  enlout_block(nnlout)=
    if paw_opt==0, 1 or 2: contribution of this block of states to the nl part of various properties
    if paw_opt==3:         contribution of this block of states to <c|S|c>  (where S=overlap when PAW)
  ==== if (signs==2) ====
    if paw_opt==0, 1, 2 or 4:
       gvnlc(2,my_nspinor*npw)=result of the aplication of the nl operator
                        or one of its derivative to the input vect.
    if paw_opt==3 or 4:
       gsc(2,my_nspinor*npw*(paw_opt/3))=result of the aplication of (I+S)
                        to the input vect. (where S=overlap when PAW)

SIDE EFFECTS

  ==== ONLY IF useylm=1
  cwaveprj(natom,my_nspinor) <type(pawcprj_type)>=projected input wave function |c> on non-local projector
                                  =<p_lmn|c> and derivatives
                                  Treatment depends on cpopt parameter:
                     if cpopt=-1, <p_lmn|in> (and derivatives)
                                  have to be computed (and not saved)
                     if cpopt= 0, <p_lmn|in> have to be computed and saved
                                  derivatives are eventually computed but not saved
                     if cpopt= 1, <p_lmn|in> and first derivatives have to be computed and saved
                                  other derivatives are eventually computed but not saved
                     if cpopt= 2  <p_lmn|in> are already in memory;
                                  only derivatives are computed here and not saved
 (if useylm=0, should have cpopt=-1)

PARENTS

      energy,forstrnps,m_invovl,m_lobpcgwf,vtowfk

CHILDREN

      dcopy,nonlop,prep_index_wavef_bandpp,prep_sort_wavef_spin,timab
      xmpi_allgather,xmpi_alltoallv

NOTES

  cprj (as well as cg) is distributed over band processors.
  Only the mod((iband-1)/mpi_enreg%bandpp,mpi_enreg%nproc_band) projected WFs are stored on each proc.

SOURCE

 85 #if defined HAVE_CONFIG_H
 86 #include "config.h"
 87 #endif
 88 
 89 #include "abi_common.h"
 90 
 91 subroutine prep_nonlop(choice,cpopt,cwaveprj,enlout_block,hamk,idir,lambdablock,&
 92 &                      blocksize,mpi_enreg,nnlout,paw_opt,signs,gsc,&
 93 &                      tim_nonlop,cwavef,gvnlc,already_transposed)
 94 
 95  use defs_basis
 96  use defs_abitypes
 97  use m_profiling_abi
 98  use m_xmpi
 99  use m_errors
100  use m_bandfft_kpt, only : bandfft_kpt,bandfft_kpt_get_ikpt
101  use m_hamiltonian, only : gs_hamiltonian_type
102  use m_pawcprj, only : pawcprj_type
103 
104 !This section has been created automatically by the script Abilint (TD).
105 !Do not modify the following lines by hand.
106 #undef ABI_FUNC
107 #define ABI_FUNC 'prep_nonlop'
108  use interfaces_18_timing
109  use interfaces_66_nonlocal
110  use interfaces_66_wfs, except_this_one => prep_nonlop
111 !End of the abilint section
112 
113  implicit none
114 
115 !Arguments ------------------------------------
116  integer,intent(in) :: blocksize,choice,cpopt,idir,signs,nnlout,paw_opt
117  logical,optional,intent(in) :: already_transposed
118  real(dp),intent(in) :: lambdablock(blocksize)
119  real(dp),intent(out) :: enlout_block(nnlout*blocksize),gvnlc(:,:),gsc(:,:)
120  real(dp),intent(inout) :: cwavef(:,:)
121  type(gs_hamiltonian_type),intent(in) :: hamk
122  type(mpi_type),intent(inout) :: mpi_enreg
123  type(pawcprj_type),intent(inout) :: cwaveprj(:,:)
124 
125 !Local variables-------------------------------
126 !scalars
127  integer :: bandpp,ier,ikpt_this_proc,my_nspinor,ndatarecv,nproc_band,npw,nspinortot
128  integer :: old_me_g0,spaceComm=0,tim_nonlop
129  logical :: do_transpose
130  character(len=500) :: msg
131 !arrays
132  integer,allocatable :: index_wavef_band(:)
133  integer,  allocatable :: rdisplsloc(:),recvcountsloc(:),sdisplsloc(:),sendcountsloc(:)
134  integer,ABI_CONTIGUOUS  pointer :: rdispls(:),recvcounts(:),sdispls(:),sendcounts(:)
135  real(dp) :: lambda_nonlop(mpi_enreg%bandpp),tsec(2)
136  real(dp), allocatable :: cwavef_alltoall2(:,:),gvnlc_alltoall2(:,:),gsc_alltoall2(:,:)
137  real(dp), allocatable :: cwavef_alltoall1(:,:),gvnlc_alltoall1(:,:),gsc_alltoall1(:,:)
138  real(dp),allocatable :: enlout(:)
139 
140 ! *************************************************************************
141 
142  DBG_ENTER('COLL')
143 
144  call timab(570,1,tsec)
145 
146  do_transpose = .true.
147  if(present(already_transposed)) then
148    if(already_transposed) do_transpose = .false.
149  end if
150 
151  nproc_band = mpi_enreg%nproc_band
152  bandpp     = mpi_enreg%bandpp
153  spaceComm=mpi_enreg%comm_fft
154  if(mpi_enreg%paral_kgb==1) spaceComm=mpi_enreg%comm_band
155  my_nspinor=max(1,hamk%nspinor/mpi_enreg%nproc_spinor)
156  nspinortot=hamk%nspinor
157 
158 !Check sizes
159  npw=hamk%npw_k;if (.not.do_transpose) npw=hamk%npw_fft_k
160  if (size(cwavef)/=2*npw*my_nspinor*blocksize) then
161    msg = 'Incorrect size for cwavef!'
162    MSG_BUG(msg)
163  end if
164  if(choice/=0.and.signs==2) then
165    if (paw_opt/=3) then
166      if (size(gvnlc)/=2*npw*my_nspinor*blocksize) then
167        msg = 'Incorrect size for gvnlc!'
168        MSG_BUG(msg)
169      end if
170    end if
171    if(paw_opt>=3) then
172      if (size(gsc)/=2*npw*my_nspinor*blocksize) then
173        msg = 'Incorrect size for gsc!'
174        MSG_BUG(msg)
175      end if
176    end if
177  end if
178  if(cpopt>=0) then
179    if (size(cwaveprj)/=hamk%natom*my_nspinor*mpi_enreg%bandpp) then
180      msg = 'Incorrect size for cwaveprj!'
181      MSG_BUG(msg)
182    end if
183  end if
184 
185  ABI_ALLOCATE(sendcountsloc,(nproc_band))
186  ABI_ALLOCATE(sdisplsloc   ,(nproc_band))
187  ABI_ALLOCATE(recvcountsloc,(nproc_band))
188  ABI_ALLOCATE(rdisplsloc   ,(nproc_band))
189 
190  ikpt_this_proc=bandfft_kpt_get_ikpt()
191 
192  recvcounts   => bandfft_kpt(ikpt_this_proc)%recvcounts(:)
193  sendcounts   => bandfft_kpt(ikpt_this_proc)%sendcounts(:)
194  rdispls      => bandfft_kpt(ikpt_this_proc)%rdispls   (:)
195  sdispls      => bandfft_kpt(ikpt_this_proc)%sdispls   (:)
196  ndatarecv    =  bandfft_kpt(ikpt_this_proc)%ndatarecv
197 
198  ABI_ALLOCATE(cwavef_alltoall2,(2,ndatarecv*my_nspinor*bandpp))
199  ABI_ALLOCATE(gsc_alltoall2,(2,ndatarecv*my_nspinor*(paw_opt/3)*bandpp))
200  ABI_ALLOCATE(gvnlc_alltoall2,(2,ndatarecv*my_nspinor*bandpp))
201 
202  if(do_transpose .and. (bandpp/=1 .or. (bandpp==1 .and. mpi_enreg%paral_spinor==0.and.nspinortot==2)))then
203    ABI_ALLOCATE(cwavef_alltoall1,(2,ndatarecv*my_nspinor*bandpp))
204    if(signs==2)then
205      if (paw_opt/=3) then
206        ABI_ALLOCATE(gvnlc_alltoall1,(2,ndatarecv*my_nspinor*bandpp))
207      end if
208      if (paw_opt==3.or.paw_opt==4) then
209        ABI_ALLOCATE(gsc_alltoall1,(2,ndatarecv*my_nspinor*bandpp))
210      end if
211    end if
212  end if
213 
214  ABI_ALLOCATE(enlout,(nnlout*bandpp))
215  enlout = zero
216 
217  recvcountsloc(:)=recvcounts(:)*2*my_nspinor*bandpp
218  rdisplsloc(:)=rdispls(:)*2*my_nspinor*bandpp
219  sendcountsloc(:)=sendcounts(:)*2*my_nspinor
220  sdisplsloc(:)=sdispls(:)*2*my_nspinor
221 
222  if(do_transpose) then
223    call timab(581,1,tsec)
224    if(bandpp/=1 .or. (bandpp==1 .and. mpi_enreg%paral_spinor==0.and.nspinortot==2))then
225      call xmpi_alltoallv(cwavef,sendcountsloc,sdisplsloc,cwavef_alltoall1,&
226 &     recvcountsloc,rdisplsloc,spaceComm,ier)
227    else
228      call xmpi_alltoallv(cwavef,sendcountsloc,sdisplsloc,cwavef_alltoall2,&
229 &     recvcountsloc,rdisplsloc,spaceComm,ier)
230    end if
231    call timab(581,2,tsec)
232  else
233    ! Here, we cheat, and use DCOPY to bypass some compiler's overzealous bound-checking
234    ! (ndatarecv*my_nspinor*bandpp might be greater than the declared size of cwavef)
235    call DCOPY(2*ndatarecv*my_nspinor*bandpp,cwavef,1,cwavef_alltoall2,1)
236  end if
237 
238  if(hamk%istwf_k==2) then
239    old_me_g0=mpi_enreg%me_g0
240    if (mpi_enreg%me_fft==0) then
241      mpi_enreg%me_g0=1
242    else
243      mpi_enreg%me_g0=0
244    end if
245  end if
246 
247 !=====================================================================
248  if (bandpp==1) then
249 
250 
251    if (do_transpose .and. mpi_enreg%paral_spinor==0.and.nspinortot==2) then !Sort WF by spin
252      call prep_sort_wavef_spin(nproc_band,my_nspinor,ndatarecv,recvcounts,rdispls,index_wavef_band)
253      cwavef_alltoall2(:, :)=cwavef_alltoall1(:,index_wavef_band)
254    end if
255 
256    if (paw_opt==2) lambda_nonlop(1)=lambdablock(mpi_enreg%me_band+1)
257    call nonlop(choice,cpopt,cwaveprj,enlout,hamk,idir,lambda_nonlop,mpi_enreg,1,nnlout,paw_opt,&
258 &   signs,gsc_alltoall2,tim_nonlop,cwavef_alltoall2,gvnlc_alltoall2)
259 
260    if (do_transpose .and. mpi_enreg%paral_spinor == 0 .and. nspinortot==2.and.signs==2) then
261      if (paw_opt/=3) gvnlc_alltoall1(:,index_wavef_band)=gvnlc_alltoall2(:,:)
262      if (paw_opt==3.or.paw_opt==4) gsc_alltoall1(:,index_wavef_band)=gsc_alltoall2(:,:)
263    end if
264 
265  else   ! bandpp/=1
266 
267 !  -------------------------------------------------------------
268 !  Computation of the index used to sort the waves functions below bandpp
269 !  -------------------------------------------------------------
270    if(do_transpose) then
271      call prep_index_wavef_bandpp(nproc_band,bandpp,&
272 &     my_nspinor,ndatarecv,recvcounts,rdispls,index_wavef_band)
273 
274 !  -------------------------------------------------------
275 !  Sorting of the waves functions below bandpp
276 !  -------------------------------------------------------
277      cwavef_alltoall2(:,:) = cwavef_alltoall1(:,index_wavef_band)
278    end if
279 
280 !  -------------------------------------------------------
281 !  Call nonlop
282 !  -------------------------------------------------------
283    if(paw_opt == 2) lambda_nonlop(1:bandpp) = lambdablock((mpi_enreg%me_band*bandpp)+1:((mpi_enreg%me_band+1)*bandpp))
284    call nonlop(choice,cpopt,cwaveprj,enlout,hamk,idir,lambda_nonlop,mpi_enreg,bandpp,nnlout,paw_opt,&
285 &   signs,gsc_alltoall2,tim_nonlop,cwavef_alltoall2,gvnlc_alltoall2)
286 
287 !  -----------------------------------------------------
288 !  Sorting of waves functions below the processors
289 !  -----------------------------------------------------
290    if(do_transpose.and.signs==2) then
291      if (paw_opt/=3) gvnlc_alltoall1(:,index_wavef_band)=gvnlc_alltoall2(:,:)
292      if (paw_opt==3.or.paw_opt==4) gsc_alltoall1(:,index_wavef_band)=gsc_alltoall2(:,:)
293    end if
294 
295  end if
296 
297 !=====================================================================
298 !  -------------------------------------------------------
299 !  Deallocation
300 !  -------------------------------------------------------
301  if (allocated(index_wavef_band)) then
302    ABI_DEALLOCATE(index_wavef_band)
303  end if
304 
305 !Transpose the gsc_alltoall or gvlnc_alltoall tabs
306 !according to the paw_opt and signs values
307  if(do_transpose) then
308    if (signs==2) then
309      call timab(581,1,tsec)
310      if(bandpp/=1 .or. (bandpp==1 .and. mpi_enreg%paral_spinor==0.and.nspinortot==2))then
311        if (paw_opt/=3) then
312          call xmpi_alltoallv(gvnlc_alltoall1,recvcountsloc,rdisplsloc,gvnlc,&
313 &         sendcountsloc,sdisplsloc,spaceComm,ier)
314        end if
315        if (paw_opt==3.or.paw_opt==4) then
316          call xmpi_alltoallv(gsc_alltoall1,recvcountsloc,rdisplsloc,gsc,&
317 &         sendcountsloc,sdisplsloc,spaceComm,ier)
318        end if
319      else
320        if (paw_opt/=3) then
321          call xmpi_alltoallv(gvnlc_alltoall2,recvcountsloc,rdisplsloc,gvnlc,&
322 &         sendcountsloc,sdisplsloc,spaceComm,ier)
323        end if
324        if (paw_opt==3.or.paw_opt==4) then
325          call xmpi_alltoallv(gsc_alltoall2,recvcountsloc,rdisplsloc,gsc,&
326 &         sendcountsloc,sdisplsloc,spaceComm,ier)
327        end if
328      end if
329      call timab(581,2,tsec)
330    end if
331  else
332    ! TODO check other usages, maybe
333    call DCOPY(2*ndatarecv*my_nspinor*bandpp, gsc_alltoall2, 1, gsc, 1)
334  end if
335  if (hamk%istwf_k==2) mpi_enreg%me_g0=old_me_g0
336 
337  if (nnlout>0) then
338    call xmpi_allgather(enlout,nnlout*bandpp,enlout_block,spaceComm,ier)
339  end if
340  ABI_DEALLOCATE(enlout)
341  ABI_DEALLOCATE(sendcountsloc)
342  ABI_DEALLOCATE(sdisplsloc)
343  ABI_DEALLOCATE(recvcountsloc)
344  ABI_DEALLOCATE(rdisplsloc)
345  ABI_DEALLOCATE(cwavef_alltoall2)
346  ABI_DEALLOCATE(gvnlc_alltoall2)
347  ABI_DEALLOCATE(gsc_alltoall2)
348  if(do_transpose .and. (bandpp/=1 .or. (bandpp==1 .and. mpi_enreg%paral_spinor==0.and.nspinortot==2)))then
349    ABI_DEALLOCATE(cwavef_alltoall1)
350    if(signs==2)then
351      if (paw_opt/=3) then
352        ABI_DEALLOCATE(gvnlc_alltoall1)
353      end if
354      if (paw_opt==3.or.paw_opt==4) then
355        ABI_DEALLOCATE(gsc_alltoall1)
356      end if
357    end if
358  end if
359 
360  call timab(570,2,tsec)
361 
362  DBG_EXIT('COLL')
363 
364 end subroutine prep_nonlop