TABLE OF CONTENTS


ABINIT/dielmt [ Functions ]

[ Top ] [ Functions ]

NAME

 dielmt

FUNCTION

 Compute dielectric matrix from susceptibility matrix
 Diagonalize it, then invert it.

COPYRIGHT

 Copyright (C) 1998-2018 ABINIT group (DCA, XG, GMR, LSI)
 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

  gmet(3,3)=reciprocal space metric tensor in bohr**-2.
  kg_diel(3,npwdiel)=reduced planewave coordinates for the dielectric matrix.
  npwdiel=size of the dielinv and susmat arrays.
  nspden=number of spin-density components
  occopt=option for occupancies
  prtvol=control print volume and debugging output
  susmat(2,npwdiel,nspden,npwdiel,nspden)=
   the susceptibility (or density-density response) matrix in reciprocal space

OUTPUT

  dielinv(2,npwdiel,(nspden+4)/3,npwdiel,(nspden+4)/3)=inverse of the (non-hermitian)
      TC dielectric matrix in reciprocal space.

NOTES

 Warning : will not work in the spin-polarized, metallic case.
 Output (not cleaned)
 !!! Spin behaviour is not obvious !!!

TODO

 Write equation below (hermitian matrix)

PARENTS

      prcref,prcref_PMA

CHILDREN

      timab,wrtout,zhpev

SOURCE

 49 #if defined HAVE_CONFIG_H
 50 #include "config.h"
 51 #endif
 52 
 53 #include "abi_common.h"
 54 
 55 subroutine dielmt(dielinv,gmet,kg_diel,&
 56 &  npwdiel,nspden,occopt,prtvol,susmat)
 57 
 58  use m_profiling_abi
 59 
 60  use defs_basis
 61 
 62 !This section has been created automatically by the script Abilint (TD).
 63 !Do not modify the following lines by hand.
 64 #undef ABI_FUNC
 65 #define ABI_FUNC 'dielmt'
 66  use interfaces_14_hidewrite
 67  use interfaces_18_timing
 68 !End of the abilint section
 69 
 70  implicit none
 71 
 72 !Arguments ------------------------------------
 73 !scalars
 74  integer,intent(in) :: npwdiel,nspden,occopt,prtvol
 75 !arrays
 76  integer,intent(in) :: kg_diel(3,npwdiel)
 77  real(dp),intent(in) :: gmet(3,3)
 78  real(dp),intent(in) :: susmat(2,npwdiel,nspden,npwdiel,nspden)
 79  real(dp),intent(out) :: dielinv(2,npwdiel,nspden,npwdiel,nspden)
 80 
 81 !Local variables-------------------------------
 82 !scalars
 83  integer :: ieig,ier,ii,index,ipw,ipw1,ipw2,isp,jj,npwsp
 84  real(dp) :: ai1,ai2,ar1,ar2,eiginv,gfact,gfactinv,gred1,gred2,gred3,gsquar
 85  real(dp) :: tpisq
 86  character(len=500) :: message
 87 !arrays
 88  real(dp) :: tsec(2)
 89  real(dp),allocatable :: dielh(:),dielmat(:,:,:,:,:),dielvec(:,:,:)
 90  real(dp),allocatable :: eig_diel(:),zhpev1(:,:),zhpev2(:)
 91 !no_abirules
 92 !integer :: ipw3
 93 !real(dp) :: elementi,elementr
 94 
 95 ! *************************************************************************
 96 
 97 !DEBUG
 98 !write(std_out,*)' dielmt : enter '
 99 !if(.true.)stop
100 !ENDDEBUG
101 
102 !tpisq is (2 Pi) **2:
103  tpisq=(two_pi)**2
104 
105  call timab(90,1,tsec)
106 
107 !-Compute now the hermitian dielectric matrix------------------------------
108 !Following remarks are only valid within RPA approximation (Kxc=0):
109 
110 !for the spin-unpolarized case, 1 - 4pi (1/G) chi0(G,Gp) (1/Gp)
111 
112 !for the spin-polarized case,
113 !( 1  0 ) - 4pi ( 1/G  1/G )   ( chi0 upup  chi0 updn )   ( 1/Gp 1/Gp )
114 !( 0  1 )       ( 1/G  1/G )   ( chi0 dnup  chi0 dndn )   ( 1/Gp 1/Gp )
115 !which is equal to
116 !( 1  0 ) - 4pi (1/G  0 ) (chi0 upup+dndn+updn+dnup  chi0 upup+dndn+updn+dnup) (1/Gp 0  )
117 !( 0  1 )       ( 0  1/G) (chi0 upup+dndn+updn+dnup  chi0 upup+dndn+updn+dnup) ( 0  1/Gp)
118 !So, if spin-polarized, sum all spin contributions
119 !Note: chi0 updn = chi0 dnup = zero for non-metallic systems
120 
121 !In the case of non-collinear magnetism, within RPA, this is the same because:
122 !chi0_(s1,s2),(s3,s4) = delta_s1,s2 * delta_s3,s4 * chi0_(s1,s1),(s3,s3)
123 !Only chi_upup,upup, chi_dndn,dndn, chi_upup,dndn and chi_dndn,upup
124 !have to be taken into account (stored, susmat(:,ipw1,1:2,ipw2,1:2)
125 
126  ABI_ALLOCATE(dielmat,(2,npwdiel,min(nspden,2),npwdiel,min(nspden,2)))
127 
128  if(nspden/=1)then
129    if (occopt<3) then
130      do ipw2=1,npwdiel
131        do ipw1=1,npwdiel
132          dielmat(1,ipw1,1,ipw2,1)=susmat(1,ipw1,1,ipw2,1)+susmat(1,ipw1,2,ipw2,2)
133          dielmat(2,ipw1,1,ipw2,1)=susmat(2,ipw1,1,ipw2,1)+susmat(2,ipw1,2,ipw2,2)
134        end do
135      end do
136    else
137      do ipw2=1,npwdiel
138        do ipw1=1,npwdiel
139          dielmat(1,ipw1,1,ipw2,1)=susmat(1,ipw1,1,ipw2,1)+susmat(1,ipw1,2,ipw2,2)+susmat(1,ipw1,1,ipw2,2)+susmat(1,ipw1,2,ipw2,1)
140          dielmat(2,ipw1,1,ipw2,1)=susmat(2,ipw1,1,ipw2,1)+susmat(2,ipw1,2,ipw2,2)+susmat(2,ipw1,1,ipw2,2)+susmat(2,ipw1,2,ipw2,1)
141        end do
142      end do
143    end if
144  else
145    do ipw2=1,npwdiel
146      do ipw1=1,npwdiel
147        dielmat(1,ipw1,1,ipw2,1)=susmat(1,ipw1,1,ipw2,1)
148        dielmat(2,ipw1,1,ipw2,1)=susmat(2,ipw1,1,ipw2,1)
149      end do
150    end do
151  end if
152 !Compute 1/G factors and include them in the dielectric matrix
153  do ipw1=1,npwdiel
154    gred1=dble(kg_diel(1,ipw1))
155    gred2=dble(kg_diel(2,ipw1))
156    gred3=dble(kg_diel(3,ipw1))
157    gsquar=tpisq*(gmet(1,1)*gred1**2+gmet(2,2)*gred2**2+gmet(3,3)*gred3**2 &
158 &   +two*( (gmet(1,2)*gred2+gmet(1,3)*gred3)* gred1 +      &
159 &   gmet(2,3)*gred2*gred3)                        )
160 !  Distinguish G=0 from other elements
161    if(gsquar>tol12)then
162 !    !$ gfact=\sqrt (4.0_dp \pi/gsquar/dble(nspden))$
163      gfact=sqrt(four_pi/gsquar)
164      do ipw2=1,npwdiel
165 !      Must multiply both rows and columns, and also changes the sign
166        dielmat(1,ipw2,1,ipw1,1)=-dielmat(1,ipw2,1,ipw1,1)*gfact
167        dielmat(2,ipw2,1,ipw1,1)=-dielmat(2,ipw2,1,ipw1,1)*gfact
168        dielmat(1,ipw1,1,ipw2,1)= dielmat(1,ipw1,1,ipw2,1)*gfact
169        dielmat(2,ipw1,1,ipw2,1)= dielmat(2,ipw1,1,ipw2,1)*gfact
170      end do
171    else
172 !    Zero the G=0 elements, head and wings
173      do ipw2=1,npwdiel
174        dielmat(1,ipw2,1,ipw1,1)=zero
175        dielmat(2,ipw2,1,ipw1,1)=zero
176        dielmat(1,ipw1,1,ipw2,1)=zero
177        dielmat(2,ipw1,1,ipw2,1)=zero
178      end do
179    end if
180  end do
181 
182 !Complete the matrix in the spin-polarized case
183 !should this be nspden==2??
184  if(nspden/=1)then
185    do ipw1=1,npwdiel
186      do ipw2=1,npwdiel
187        dielmat(1,ipw1,1,ipw2,2)=dielmat(1,ipw1,1,ipw2,1)
188        dielmat(2,ipw1,1,ipw2,2)=dielmat(2,ipw1,1,ipw2,1)
189        dielmat(1,ipw1,2,ipw2,1)=dielmat(1,ipw1,1,ipw2,1)
190        dielmat(2,ipw1,2,ipw2,1)=dielmat(2,ipw1,1,ipw2,1)
191        dielmat(1,ipw1,2,ipw2,2)=dielmat(1,ipw1,1,ipw2,1)
192        dielmat(2,ipw1,2,ipw2,2)=dielmat(2,ipw1,1,ipw2,1)
193      end do
194    end do
195  end if
196 
197 !DEBUG
198 !write(std_out,*)' dielmt : make dielmat equal to identity matrix '
199 !do ipw1=1,npwdiel
200 !do ipw2=1,npwdiel
201 !dielmat(1,ipw1,1,ipw2,1)=0.0_dp
202 !dielmat(2,ipw1,1,ipw2,1)=0.0_dp
203 !end do
204 !end do
205 !ENDDEBUG
206 
207 !Add the diagonal part
208  do isp=1,min(nspden,2)
209    do ipw=1,npwdiel
210      dielmat(1,ipw,isp,ipw,isp)=one+dielmat(1,ipw,isp,ipw,isp)
211    end do
212  end do
213 
214 !-The hermitian dielectric matrix is computed ------------------------------
215 !-Now, diagonalize it ------------------------------------------------------
216 
217 !In RPA, everything is projected on the spin-symmetrized
218 !space. This was coded here (for the time being).
219 
220 !Diagonalize the hermitian dielectric matrix
221 
222 !npwsp=npwdiel*nspden
223  npwsp=npwdiel
224 
225  ABI_ALLOCATE(dielh,(npwsp*(npwsp+1)))
226  ABI_ALLOCATE(dielvec,(2,npwsp,npwsp))
227  ABI_ALLOCATE(eig_diel,(npwsp))
228  ABI_ALLOCATE(zhpev1,(2,2*npwsp-1))
229  ABI_ALLOCATE(zhpev2,(3*npwsp-2))
230  ier=0
231 !Store the dielectric matrix in proper mode before calling zhpev
232  index=1
233  do ii=1,npwdiel
234    do jj=1,ii
235      dielh(index  )=dielmat(1,jj,1,ii,1)
236      dielh(index+1)=dielmat(2,jj,1,ii,1)
237      index=index+2
238    end do
239  end do
240 !If spin-polarized and non RPA, need to store other parts of the matrix
241 !if(nspden/=1)then
242 !do ii=1,npwdiel
243 !Here, spin-flip contribution
244 !do jj=1,npwdiel
245 !dielh(index  )=dielmat(1,jj,1,ii,2)
246 !dielh(index+1)=dielmat(2,jj,1,ii,2)
247 !index=index+2
248 !end do
249 !Here spin down-spin down upper matrix
250 !do jj=1,ii
251 !dielh(index  )=dielmat(1,jj,2,ii,2)
252 !dielh(index+1)=dielmat(2,jj,2,ii,2)
253 !index=index+2
254 !end do
255 !end do
256 !end if
257 
258  call ZHPEV ('V','U',npwsp,dielh,eig_diel,dielvec,npwdiel,zhpev1,&
259 & zhpev2,ier)
260  ABI_DEALLOCATE(zhpev1)
261  ABI_DEALLOCATE(zhpev2)
262 
263  if(prtvol>=10)then
264    write(message, '(a,a,a,5es12.4)' )ch10,&
265 &   ' Five largest eigenvalues of the hermitian RPA dielectric matrix:',&
266 &   ch10,eig_diel(npwdiel:npwdiel-4:-1)
267    call wrtout(ab_out,message,'COLL')
268  end if
269 
270  write(message, '(a,a)' )ch10,&
271 & ' dielmt : 15 largest eigenvalues of the hermitian RPA dielectric matrix'
272  call wrtout(std_out,message,'COLL')
273  write(message, '(a,5es12.5)' )'  1-5  :',eig_diel(npwdiel:npwdiel-4:-1)
274  call wrtout(std_out,message,'COLL')
275  write(message, '(a,5es12.5)' )'  6-10 :',eig_diel(npwdiel-5:npwdiel-9:-1)
276  call wrtout(std_out,message,'COLL')
277  write(message, '(a,5es12.5)' )'  11-15:',eig_diel(npwdiel-10:npwdiel-14:-1)
278  call wrtout(std_out,message,'COLL')
279  write(message, '(a,a)' )ch10,&
280 & ' dielmt : 5 smallest eigenvalues of the hermitian RPA dielectric matrix'
281  call wrtout(std_out,message,'COLL')
282  write(message, '(a,5es12.5)' )'  1-5  :',eig_diel(1:5)
283  call wrtout(std_out,message,'COLL')
284 
285 !Invert the hermitian dielectric matrix,
286 !Should use a BLAS call !
287  do ipw2=1,npwdiel
288    do ipw1=ipw2,npwdiel
289      dielinv(1,ipw1,1,ipw2,1)=zero  
290      dielinv(2,ipw1,1,ipw2,1)=zero  
291    end do
292  end do
293  do ieig=1,npwdiel
294    eiginv=one/eig_diel(ieig)
295    do ipw2=1,npwdiel
296      do ipw1=ipw2,npwdiel
297        ar1=dielvec(1,ipw1,ieig)
298        ai1=dielvec(2,ipw1,ieig)
299        ar2=dielvec(1,ipw2,ieig)
300        ai2=dielvec(2,ipw2,ieig)
301        dielinv(1,ipw1,1,ipw2,1)=dielinv(1,ipw1,1,ipw2,1)+&
302 &       (ar1*ar2+ai1*ai2)*eiginv
303        dielinv(2,ipw1,1,ipw2,1)=dielinv(2,ipw1,1,ipw2,1)+&
304 &       (ai1*ar2-ar1*ai2)*eiginv
305      end do
306    end do
307  end do
308  do ipw2=1,npwdiel-1
309    do ipw1=ipw2+1,npwdiel
310      dielinv(1,ipw2,1,ipw1,1)= dielinv(1,ipw1,1,ipw2,1)
311      dielinv(2,ipw2,1,ipw1,1)=-dielinv(2,ipw1,1,ipw2,1)
312    end do
313  end do
314 
315  ABI_DEALLOCATE(dielh)
316  ABI_DEALLOCATE(dielvec)
317  ABI_DEALLOCATE(eig_diel)
318 
319 !DEBUG
320 !Checks whether the inverse of the hermitian dielectric matrix
321 !has been correctly generated
322 !do ipw1=1,npwdiel
323 !do ipw2=1,npwdiel
324 !elementr=0.0_dp
325 !elementi=0.0_dp
326 !do ipw3=1,npwdiel
327 !elementr=elementr+dielinv(1,ipw1,1,ipw3,1)*dielmat(1,ipw3,1,ipw2,1)&
328 !&                    -dielinv(2,ipw1,1,ipw3,1)*dielmat(2,ipw3,1,ipw2,1)
329 !elementi=elementi+dielinv(1,ipw1,1,ipw3,1)*dielmat(2,ipw3,1,ipw2,1)&
330 !&                    +dielinv(2,ipw1,1,ipw3,1)*dielmat(1,ipw3,1,ipw2,1)
331 !end do
332 !if(elementr**2+elementi**2 > 1.0d-12)then
333 !if( ipw1 /= ipw2 .or. &
334 !&        ( abs(elementr-1.0_dp)>1.0d-6 .or. abs(elementi)>1.0d-6 ))then
335 !write(std_out,*)' dielmt : the inversion procedure is not correct '
336 !write(std_out,*)' ipw1, ipw2 =',ipw1,ipw2
337 !write(std_out,*)' elementr,elementi=',elementr,elementi
338 !stop
339 !end if
340 !end if
341 !end do
342 !end do
343 !write(std_out,*)'dielmt : matrix has been inverted successfully '
344 !stop
345 !ENDDEBUG
346 
347 !Then get the inverse of the asymmetric
348 !dielectric matrix, as required for the preconditioning.
349 
350 !Inverse of the dielectric matrix : ( 1 - 4pi (1/G^2) chi0(G,Gp) )^(-1)
351 !In dielinv there is now (1 - 4pi (1/G) chi0(G,Gp) (1/Gp) )^(-1)
352 !So, evaluate dielinv_after(G,Gp) =
353 !(4pi/G^2)^(1/2) dielinv_before(G,Gp) (4pi/Gp^2)^(-1/2)
354 !In RPA, can focus on the spin-averaged quantities
355  do ipw1=1,npwdiel
356    gred1=dble(kg_diel(1,ipw1))
357    gred2=dble(kg_diel(2,ipw1))
358    gred3=dble(kg_diel(3,ipw1))
359    gsquar=tpisq*(gmet(1,1)*gred1**2+gmet(2,2)*gred2**2+gmet(3,3)*gred3**2 &
360 &   +two*( (gmet(1,2)*gred2+gmet(1,3)*gred3)* gred1 +      &
361 &   gmet(2,3)*gred2*gred3)                        )
362 !  Distinguish G=0 from other elements
363    if(gsquar>tol12)then
364      gfact=sqrt(four_pi/gsquar)
365      gfactinv=one/gfact
366      do ipw2=1,npwdiel
367 !      Must multiply both rows and columns
368        dielinv(1,ipw2,1,ipw1,1)=dielinv(1,ipw2,1,ipw1,1)*gfactinv
369        dielinv(2,ipw2,1,ipw1,1)=dielinv(2,ipw2,1,ipw1,1)*gfactinv
370        dielinv(1,ipw1,1,ipw2,1)=dielinv(1,ipw1,1,ipw2,1)*gfact
371        dielinv(2,ipw1,1,ipw2,1)=dielinv(2,ipw1,1,ipw2,1)*gfact
372      end do
373    else
374 !    Zero the G=0 elements, head
375      do ipw2=1,npwdiel
376        if (ipw2/=ipw1) dielinv(1:2,ipw1,1,ipw2,1)=zero
377      end do
378    end if
379  end do
380 
381  ABI_DEALLOCATE(dielmat)
382 
383  call timab(90,2,tsec)
384 
385 end subroutine dielmt