TABLE OF CONTENTS


ABINIT/dotprodm_vn [ Functions ]

[ Top ] [ Functions ]

NAME

 dotprodm_vn

FUNCTION

 For a set of densities and a set of potentials,
 compute the dot product (integral over FFT grid) of each pair, to obtain
 a series of energy-like quantity (so the usual dotproduct is divided
 by the number of FFT points, and multiplied by the primitive cell volume).
 Take into account the spin components of the density and potentials (nspden),
 and sum correctly over them. Note that the storage of densities and
 potentials is different : for potential, one stores the matrix components,
 while for the density, one stores the trace, and then, either the
 spin-polarisation (if nspden=2), or the magnetization vector (if nspden=4).
 Need the index of the first density/potential pair to be treated, in each array,
 and the number of pairs to be treated.
 Might be used to compute just one dot product, in
 a big array, such as to avoid copying the density and potential from a big array
 to a temporary place.

COPYRIGHT

 Copyright (C) 1999-2018 ABINIT group (XG)
 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

  cplex=if 1, real space functions on FFT grid are REAL, if 2, COMPLEX
  cpldot=if 1, the dot array is real, if 2, the dot array is complex (not coded yet for nspden=4)
  denarr(cplex*nfft,nspden,nden)=real space density on FFT grid
  id=index of the first density to be treated in the denarr array
  ip=index of the first potential to be treated in the potarr array
  mpicomm=the mpi communicator used for the summation
  mpi_summarize=set it to .true. if parallelisation is done over FFT
  multd=number of densities to be treated
  multp=number of potentials to be treated
  nden=third dimension of the denarr array
  nfft= (effective) number of FFT grid points (for this processor)
  nfftot= total number of FFT grid points
  npot=third dimension of the potarr array
  nspden=number of spin-density components
  potarr(cplex*nfft,nspden,npot)=real space potential on FFT grid
                 (will be complex conjugated if cplex=2 and cpldot=2)
  ucvol=unit cell volume (Bohr**3)

OUTPUT

  dot(cpldot,multp,multd)= series of values of the dot product potential/density

SIDE EFFECTS

NOTES

  Concerning storage when nspden=4:
   cplex=1:
     V are stored as : V^11, V^22, Re[V^12], Im[V^12] (complex, hermitian)
     N are stored as : n, m_x, m_y, m_z               (real)
   cplex=2:
     V are stored as : V^11, V^22, V^12, i.V^21 (complex)
     N are stored as : n, m_x, m_y, mZ          (complex)

PARENTS

      aprxdr

CHILDREN

      timab,xmpi_sum

SOURCE

 71 #if defined HAVE_CONFIG_H
 72 #include "config.h"
 73 #endif
 74 
 75 #include "abi_common.h"
 76 
 77 
 78 subroutine dotprodm_vn(cplex,cpldot,denarr,dot,id,ip,mpicomm, mpi_summarize,multd,multp,&
 79 & nden,nfft,nfftot,npot,nspden,potarr,ucvol)
 80 
 81  use defs_basis
 82  use m_errors
 83  use m_profiling_abi
 84  use m_xmpi
 85 
 86 !This section has been created automatically by the script Abilint (TD).
 87 !Do not modify the following lines by hand.
 88 #undef ABI_FUNC
 89 #define ABI_FUNC 'dotprodm_vn'
 90  use interfaces_18_timing
 91 !End of the abilint section
 92 
 93  implicit none
 94 
 95 !Arguments ------------------------------------
 96 !scalars
 97  integer,intent(in) :: cpldot,cplex,id,ip,multd,multp,nden,nfft,nfftot,npot
 98  integer,intent(in) :: nspden,mpicomm
 99  logical, intent(in) :: mpi_summarize
100  real(dp),intent(in) :: ucvol
101 !arrays
102  real(dp),intent(in) :: denarr(cplex*nfft,nspden,nden)
103  real(dp),intent(in) :: potarr(cplex*nfft,nspden,npot)
104  real(dp),intent(out) :: dot(cpldot,multp,multd)
105 
106 !Local variables-------------------------------
107 !scalars
108  integer :: i1,i2,ierr,ir,jr
109  real(dp) :: ai,ar,dim11,dim12,dim21,dim22,dim_dn,dim_up,dre11,dre12,dre21
110  real(dp) :: dre22,dre_dn,dre_up,factor,pim11,pim12,pim21,pim22,pim_dn,pim_up
111  real(dp) :: pre11,pre12,pre21,pre22,pre_dn,pre_up
112 !arrays
113  real(dp) :: tsec(2)
114 
115 ! *************************************************************************
116 
117 !Real or complex inputs are coded
118  DBG_CHECK(ANY(cplex==(/1,2/)),"Wrong cplex")
119 
120 !Real or complex outputs are coded
121  DBG_CHECK(ANY(cpldot==(/1,2/)),"Wrong cpldot")
122  DBG_CHECK(ANY(nspden==(/1,2,4/)),"Wrong nspden")
123 
124  DBG_CHECK(id >= 1,'Wrong id')
125  DBG_CHECK(ip >= 1,'Wrong id')
126 
127  DBG_CHECK(multd >= 1,"wrong multd")
128  DBG_CHECK(multp >= 1,"wrong multp")
129 
130  DBG_CHECK(nden-id-multd >=-1,'nden-id-multd')
131  DBG_CHECK(npot-ip-multp >=-1,'npot-ip-multp')
132 
133  if(nspden==1)then
134 
135    if(cpldot==1 .or. cplex==1 )then
136 
137      do i2=1,multd
138        do i1=1,multp
139          ar=zero
140 !$OMP PARALLEL DO PRIVATE(ir) SHARED(id,i1,i2,ip,cplex,nfft,denarr,potarr) REDUCTION(+:ar)
141          do ir=1,cplex*nfft
142            ar=ar + potarr(ir,1,ip+i1-1)*denarr(ir,1,id+i2-1)
143          end do
144          dot(1,i1,i2)=ar
145        end do ! i1
146      end do ! i2
147 
148    else  ! cpldot==2 and cplex==2 : one builds the imaginary part, from complex den/pot
149 
150      do i2=1,multd
151        do i1=1,multp
152          ar=zero ; ai=zero
153 !$OMP PARALLEL DO PRIVATE(ir,jr) SHARED(id,i1,i2,ip,nfft,denarr,potarr) REDUCTION(+:ar,ai)
154          do ir=1,nfft
155            jr=2*ir
156            ar=ar + potarr(jr-1,1,ip+i1-1)*denarr(jr-1,1,id+i2-1) &
157 &           + potarr(jr  ,1,ip+i1-1)*denarr(jr  ,1,id+i2-1)
158            ai=ai + potarr(jr-1,1,ip+i1-1)*denarr(jr  ,1,id+i2-1) &
159 &           - potarr(jr  ,1,ip+i1-1)*denarr(jr-1,1,id+i2-1)
160          end do
161          dot(1,i1,i2)=ar ; dot(2,i1,i2)=ai
162        end do ! i1
163      end do ! i2
164 
165    end if
166 
167  else if(nspden==2)then
168 
169    if(cpldot==1 .or. cplex==1 )then
170 
171      do i2=1,multd
172        do i1=1,multp
173          ar=zero
174 !$OMP PARALLEL DO PRIVATE(ir) SHARED(id,i1,i2,ip,cplex,nfft,denarr,potarr) REDUCTION(+:ar)
175          do ir=1,cplex*nfft
176            ar=ar + potarr(ir,1,ip+i1-1)* denarr(ir,2,id+i2-1)               &       ! This is the spin up contribution
177 &          + potarr(ir,2,ip+i1-1)*(denarr(ir,1,id+i2-1)-denarr(ir,2,id+i2-1)) ! This is the spin down contribution
178          end do
179          dot(1,i1,i2)=ar
180        end do ! i1
181      end do ! i2
182 
183    else ! cpldot==2 and cplex==2 : one builds the imaginary part, from complex den/pot
184 
185      do i2=1,multd
186        do i1=1,multp
187          ar=zero ; ai=zero
188 !$OMP PARALLEL DO PRIVATE(ir,jr,dre_up,dim_up,dre_dn,dim_dn,pre_up,pim_up,pre_dn,pim_dn) &
189 !$OMP&SHARED(id,i1,i2,ip,nfft,denarr,potarr) REDUCTION(+:ar,ai)
190          do ir=1,nfft
191            jr=2*ir
192 
193            dre_up=denarr(jr-1,2,id+i2-1)
194            dim_up=denarr(jr  ,2,id+i2-1)
195            dre_dn=denarr(jr-1,1,id+i2-1)-dre_up
196            dim_dn=denarr(jr  ,1,id+i2-1)-dim_up
197 
198            pre_up=potarr(jr-1,1,ip+i1-1)
199            pim_up=potarr(jr  ,1,ip+i1-1)
200            pre_dn=potarr(jr-1,2,ip+i1-1)
201            pim_dn=potarr(jr  ,2,ip+i1-1)
202 
203            ar=ar + pre_up * dre_up &
204 &           + pim_up * dim_up &
205 &           + pre_dn * dre_dn &
206 &           + pim_dn * dim_dn
207            ai=ai + pre_up * dim_up &
208 &           - pim_up * dre_up &
209 &           + pre_dn * dim_dn &
210 &           - pim_dn * dre_dn
211 
212          end do
213          dot(1,i1,i2)=ar ; dot(2,i1,i2)=ai
214        end do ! i1
215      end do ! i2
216 
217    end if
218 
219  else if(nspden==4)then
220 !  \rho{\alpha,\beta} V^{\alpha,\beta} =
221 !  rho*(V^{11}+V^{22})/2$
222 !  + m_x Re(V^{12})- m_y Im{V^{12}}+ m_z(V^{11}-V^{22})/2
223    if (cplex==1) then
224      do i2=1,multd
225        do i1=1,multp
226          ar=zero
227 !$OMP PARALLEL DO PRIVATE(ir) SHARED(id,i1,i2,ip,cplex,nfft,denarr,potarr) REDUCTION(+:ar)
228          do ir=1,cplex*nfft
229            ar=ar+(potarr(ir,1,ip+i1-1)+potarr(ir,2,ip+i1-1))*half*denarr(ir,1,id+i2-1)& ! This is the density contrib
230 &          + potarr(ir,3,ip+i1-1)                                *denarr(ir,2,id+i2-1)& ! This is the m_x contrib
231 &          - potarr(ir,4,ip+i1-1)                                *denarr(ir,3,id+i2-1)& ! This is the m_y contrib
232 &          +(potarr(ir,1,ip+i1-1)-potarr(ir,2,ip+i1-1))*half*denarr(ir,4,id+i2-1)       ! This is the m_z contrib
233          end do
234          dot(1,i1,i2)=ar
235        end do ! i1
236      end do ! i2
237    else ! cplex=2
238 !    Note concerning storage when cplex=2:
239 !    V are stored as : v^11, v^22, V^12, i.V^21 (each are complex)
240 !    N are stored as : n, m_x, m_y, mZ          (each are complex)
241      if (cpldot==1) then
242        do i2=1,multd
243          do i1=1,multp
244            ar=zero ; ai=zero
245 !$OMP PARALLEL DO PRIVATE(ir,jr,dre11,dim11,dre22,dim22,dre12,dim12,pre11,pim11,pre22,pim22,pre12,pim12) &
246 !$OMP&SHARED(id,i1,i2,ip,nfft,denarr,potarr) REDUCTION(+:ar)
247            do ir=1,nfft
248              jr=2*ir
249              dre11=half*(denarr(jr-1,1,id+i2)+denarr(jr-1,4,id+i2))
250              dim11=half*(denarr(jr  ,1,id+i2)+denarr(jr-1,4,id+i2))
251              dre22=half*(denarr(jr-1,1,id+i2)-denarr(jr-1,4,id+i2))
252              dim22=half*(denarr(jr  ,1,id+i2)-denarr(jr-1,4,id+i2))
253              dre12=half*(denarr(jr-1,2,id+i2)+denarr(jr  ,3,id+i2))
254              dim12=half*(denarr(jr  ,2,id+i2)-denarr(jr-1,3,id+i2))
255              dre21=half*(denarr(jr-1,2,id+i2)-denarr(jr  ,3,id+i2))
256              dim21=half*(denarr(jr  ,2,id+i2)+denarr(jr-1,3,id+i2))
257              pre11= potarr(jr-1,1,ip+i1)
258              pim11= potarr(jr  ,1,ip+i1)
259              pre22= potarr(jr-1,2,ip+i1)
260              pim22= potarr(jr  ,2,ip+i1)
261              pre12= potarr(jr-1,3,ip+i1)
262              pim12= potarr(jr  ,3,ip+i1)
263              pre21= potarr(jr  ,4,ip+i1)
264              pim21=-potarr(jr-1,4,ip+i1)
265              ar=ar + pre11 * dre11 &
266 &             + pim11 * dim11 &
267 &             + pre22 * dre22 &
268 &             + pim22 * dim22 &
269 &             + pre12 * dre12 &
270 &             + pim12 * dim12 &
271 &             + pre21 * dre21 &
272 &             + pim21 * dim21
273            end do
274            dot(1,i1,i2)=ar
275          end do ! i1
276        end do ! i2
277      else !cpldot=2
278        do i2=1,multd
279          do i1=1,multp
280            ar=zero ; ai=zero
281 !$OMP PARALLEL DO PRIVATE(ir,jr,dre11,dim11,dre22,dim22,dre12,dim12,pre11,pim11,pre12,pim12,pre22,pim22) &
282 !$OMP&SHARED(id,i1,i2,ip,nfft,denarr,potarr) REDUCTION(+:ar,ai)
283            do ir=1,nfft
284              jr=2*ir
285              dre11=half*(denarr(jr-1,1,id+i2)+denarr(jr-1,4,id+i2))
286              dim11=half*(denarr(jr  ,1,id+i2)+denarr(jr-1,4,id+i2))
287              dre22=half*(denarr(jr-1,1,id+i2)-denarr(jr-1,4,id+i2))
288              dim22=half*(denarr(jr  ,1,id+i2)-denarr(jr-1,4,id+i2))
289              dre12=half*(denarr(jr-1,2,id+i2)+denarr(jr  ,3,id+i2))
290              dim12=half*(denarr(jr  ,2,id+i2)-denarr(jr-1,3,id+i2))
291              dre21=half*(denarr(jr-1,2,id+i2)-denarr(jr  ,3,id+i2))
292              dim21=half*(denarr(jr  ,2,id+i2)+denarr(jr-1,3,id+i2))
293              pre11= potarr(jr-1,1,ip+i1)
294              pim11= potarr(jr  ,1,ip+i1)
295              pre22= potarr(jr-1,2,ip+i1)
296              pim22= potarr(jr  ,2,ip+i1)
297              pre12= potarr(jr-1,3,ip+i1)
298              pim12= potarr(jr  ,3,ip+i1)
299              pre21= potarr(jr  ,4,ip+i1)
300              pim21=-potarr(jr-1,4,ip+i1)
301              ar=ar + pre11 * dre11 &
302 &             + pim11 * dim11 &
303 &             + pre22 * dre22 &
304 &             + pim22 * dim22 &
305 &             + pre12 * dre12 &
306 &             + pim12 * dim12 &
307 &             + pre21 * dre21 &
308 &             + pim21 * dim21
309              ai=ai + pre11 * dim11 &
310 &             - pim11 * dre11 &
311 &             + pre22 * dim22 &
312 &             - pim22 * dre22 &
313 &             + pre12 * dim12 &
314 &             - pim12 * dre12 &
315 &             + pre21 * dim21 &
316 &             - pim21 * dre21
317            end do
318            dot(1,i1,i2)=ar
319            dot(2,i1,i2)=ai
320          end do ! i1
321        end do ! i2
322      end if ! cpldot
323    end if ! cplex
324  end if ! nspden
325 
326  factor=ucvol/dble(nfftot)
327  dot(:,:,:)=factor*dot(:,:,:)
328 
329 !XG030513 : MPIWF reduction (addition) on dot is needed here
330  if (mpi_summarize) then
331    call timab(48,1,tsec)
332    call xmpi_sum(dot,mpicomm ,ierr)
333    call timab(48,2,tsec)
334  end if
335 
336  if(cpldot==2 .and. cplex==1)dot(2,:,:)=zero
337 
338 end subroutine dotprodm_vn