TABLE OF CONTENTS


ABINIT/listkk [ Functions ]

[ Top ] [ Functions ]

NAME

 listkk

FUNCTION

 Given a list of nkpt1 initial k points kptns1 and a list of nkpt2
 final k points kptns2, associates each final k pt with a "closest"
 initial k point (or symmetric thereof, also taking possible umklapp)
 as determined by a metric gmet, that commutes with the symmetry operations.
 The algorithm does not scale as nkpt1 times nkpt2, thanks
 to the ordering of the kptns1 and kptns2 vectors according to their
 lengths, and comparison first between vectors of similar lengths.
 Returns indirect indexing list indkk.

COPYRIGHT

 Copyright (C) 1998-2018 ABINIT group (DCA, XG, GMR)
 This file is distributed under the terms of the
 GNU General Public License, see ~abinit/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .

INPUTS

  gmet(3,3)=reciprocal space metric (bohr^-2)
  kptns1(3,nkpt1)=list of initial k points (reduced coordinates)
  kptns2(3,nkpt2)=list of final k points
  nkpt1=number of initial k points
  nkpt2=number of final k points
  nsym=number of symmetry elements in space group
  sppoldbl=if 1, no spin-polarisation doubling
           if 2, spin-polarisation doubling using symafm
  symafm(nsym)=(anti)ferromagnetic part of symmetry operations
  symmat(3,3,nsym)=symmetry operations (symrel or symrec, depending on
                   value of use_symrec
  timrev=1 if the use of time-reversal is allowed; 0 otherwise
  use_symrec: if present and true, symmat assumed to be symrec, otherwise assumed to be symrel (default)

OUTPUT

  dksqmax=maximal value of the norm**2 of the difference between
    a kpt2 vector and the closest k-point found from the kptns1 set, using symmetries.
  indkk(nkpt2*sppoldbl,6)=describe k point number of kpt1 that allows to
    generate wavefunctions closest to given kpt2
    if sppoldbl=2, use symafm to generate spin down wfs from spin up wfs

    indkk(:,1)=k point number of kptns1
    indkk(:,2)=symmetry operation to be applied to kpt1, to give kpt1a
      (if 0, means no symmetry operation, equivalent to identity )
    indkk(:,3:5)=shift in reciprocal space to be given to kpt1a,
      to give kpt1b, that is the closest to kpt2.
    indkk(:,6)=1 if time-reversal was used to generate kpt1a from kpt1, 0 otherwise

NOTES

  The tolerances tol12 and tol8 aims at giving a machine-independent ordering.
  (this trick is used in bonds.f, listkk.f, prtrhomxmn.f and rsiaf9.f)
  The tolerance tol12 is used for each component of the k vectors,
  and for the length of the vectors
  while the tolerance tol8 is used for the comparison of the squared lengths
  of the separate vectors.

PARENTS

      initberry,initorbmag,inwffil,m_dvdb,m_ebands,m_eprenorms,m_exc_diago
      m_fock,m_fstab,m_haydock,m_ifc,m_kpts,m_phgamma,m_sigmaph,mlwfovlp_qp

CHILDREN

      sort_dp,timab

SOURCE

 68 #if defined HAVE_CONFIG_H
 69 #include "config.h"
 70 #endif
 71 
 72 #include "abi_common.h"
 73 
 74 
 75 subroutine listkk(dksqmax,gmet,indkk,kptns1,kptns2,nkpt1,nkpt2,nsym,&
 76 & sppoldbl,symafm,symmat,timrev,use_symrec)
 77 
 78  use defs_basis
 79  use m_errors
 80  use m_profiling_abi
 81  use m_sort
 82 
 83 !This section has been created automatically by the script Abilint (TD).
 84 !Do not modify the following lines by hand.
 85 #undef ABI_FUNC
 86 #define ABI_FUNC 'listkk'
 87  use interfaces_18_timing
 88 !End of the abilint section
 89 
 90  implicit none
 91 
 92 !Arguments ------------------------------------
 93 !scalars
 94  integer,intent(in) :: nkpt1,nkpt2,nsym,sppoldbl,timrev
 95  real(dp),intent(out) :: dksqmax
 96  logical,optional,intent(in) :: use_symrec
 97 !arrays
 98  integer,intent(in) :: symafm(nsym),symmat(3,3,nsym)
 99  integer,intent(out) :: indkk(nkpt2*sppoldbl,6)
100  real(dp),intent(in) :: gmet(3,3),kptns1(3,nkpt1),kptns2(3,nkpt2)
101 
102 !Local variables-------------------------------
103 !scalars
104  integer :: l3,ig1,ig2,ig3,ii,ikpg1,ikpt1,ikpt2,ikpt2_done
105  integer :: ilarger,ismaller,itrial
106  integer :: isppol,isym,itimrev,jkpt1,jsym,jtime,limit
107  integer :: nsym_used,timrev_used,usesym
108  real(dp) :: dksq,dksqmn,lk2,llarger,ldiff,lsmaller,ltrial,min_l
109  character(len=500) :: message
110 !arrays
111  integer :: dkint(3),jdkint(3),k1int(3),k2int(3)
112  integer, allocatable :: isort(:)
113  real(dp) :: tsec(2)
114  real(dp) :: dk(3),kpg1(3),kpt1a(3),k1(3),k2(3)
115 !real(dp) :: kasq,ka(3)
116  real(dp),allocatable :: lkpg1(:),lkpg1_sorted(:)
117 
118 ! *************************************************************************
119 
120 !write(std_out,*)' listkk : nkpt1,nkpt2,nsym=',nkpt1,nkpt2,nsym
121  call timab(1021,1,tsec)
122 
123  if(sppoldbl<1 .or. sppoldbl>2)then
124    write(message, '(a,i4,3a)' )&
125 &   'The value of sppoldbl is',sppoldbl,',',ch10,&
126 &   'but it should be either 1 or 2.'
127    MSG_BUG(message)
128  end if
129 
130 !When usesym=0, the old way of converting the wavefunctions (without
131 !using the symmetries), is recovered.
132  usesym=1
133 
134  nsym_used=nsym
135  timrev_used=timrev
136  if(usesym==0)nsym_used=1
137  if(usesym==0)timrev_used=0
138 
139 !Precompute the length of the kpt1 vectors, also taking into account
140 !possible umpklapp vectors
141  limit=1 ; l3 = (2*limit+1)**3
142  ABI_ALLOCATE(lkpg1,(l3*nkpt1))
143  ABI_ALLOCATE(lkpg1_sorted,(l3*nkpt1))
144  ABI_ALLOCATE(isort,(l3*nkpt1))
145 !write(std_out,*)' List of kpt1 vectors '
146 !write(std_out,*)' Length of the kpt1 vectors :'
147 
148  do ikpt1=1,nkpt1
149    k1(:)=kptns1(:,ikpt1)
150 !  write(std_out,*)ikpt1,k1(:)
151    k1int(:)=nint(k1(:)+tol12)
152    k1(:)=k1(:)-k1int(:)
153    do ig1=-limit,limit
154      kpg1(1)=k1(1)+ig1
155      do ig2=-limit,limit
156        kpg1(2)=k1(2)+ig2
157        do ig3=-limit,limit
158          kpg1(3)=k1(3)+ig3
159 
160          ikpg1=ig1+limit+1 + (2*limit+1)*(ig2+limit) + (2*limit+1)**2*(ig3+limit) + l3*(ikpt1-1)
161 !        Compute the norm of the vector (also taking into account possible umklapp)
162          lkpg1(ikpg1)=sqrt(gmet(1,1)*kpg1(1)**2+gmet(2,2)*kpg1(2)**2+&
163 &         gmet(3,3)*kpg1(3)**2+two*(gmet(2,1)*kpg1(2)*kpg1(1)+&
164 &         gmet(3,2)*kpg1(3)*kpg1(2)+gmet(3,1)*kpg1(3)*kpg1(1)))
165          lkpg1_sorted(ikpg1)=lkpg1(ikpg1)
166          isort(ikpg1)=ikpg1
167 !        write(std_out,*)' ikpt1,ig1,ig2,ig3,lkpg1=',ikpt1,ig1,ig2,ig3,lkpg1(ikpg1)
168        end do
169      end do
170    end do
171  end do
172 
173  call sort_dp( l3*nkpt1,lkpg1_sorted,isort,tol12)
174 
175 !DEBUG
176 !write(std_out,*)' listkk : output list of kpt1 for checking purposes '
177 !write(std_out,*)' ii,ikpt1,isort(ii)-l3*(ikpt1-1),lkpg1_sorted(ii),lkpg1(isort(ii)) '
178 !do ii=1,l3*nkpt1
179 !ikpt1=(isort(ii)-1)/l3+1
180 !write(std_out,*)ii,ikpt1,isort(ii)-l3*(ikpt1-1),lkpg1_sorted(ii),lkpg1(isort(ii))
181 !enddo
182 !stop
183 !ENDDEBUG
184 
185  dksqmax=zero
186  do isppol=1,sppoldbl
187    do ikpt2=1,nkpt2
188 
189      ikpt2_done=0
190 !    Precompute the length of the kpt2 vector, with the Umklapp vector such that it is the closest to the Gamma point
191      k2(:)=kptns2(:,ikpt2)
192      k2int(:)=nint(k2(:)+tol12)
193      k2(:)=k2(:)-k2int(:)
194      lk2=sqrt(gmet(1,1)*k2(1)**2+gmet(2,2)*k2(2)**2+&
195 &     gmet(3,3)*k2(3)**2+two*(gmet(2,1)*k2(2)*k2(1)+&
196 &     gmet(3,2)*k2(3)*k2(2)+gmet(3,1)*k2(3)*k2(1)))
197 
198 !    DEBUG
199 !    write(std_out, '(a,i4,7es16.6)' )' listkk : ikpt2,kptns2(:,ikpt2),k2(:),lk2=',ikpt2,kptns2(:,ikpt2),k2(:),lk2
200 !    if(ikpt2/=17)cycle
201 !    ENDDEBUG
202 
203 !    Find the kpt1 vector whose length is the most similar to the length of lk2
204 !    up to a tolerance. Use a bissection algorithm.
205      ismaller=0       ; lsmaller=zero
206      ilarger=l3*nkpt1+1 ; llarger=huge(one)
207 !    This loop should never reach l3*nkpt1, since this is a bissection algorithm
208      do ii=1,l3*nkpt1
209        if((ilarger-ismaller)<2 .or. (llarger-lsmaller)<2*tol12)exit
210        itrial=(ilarger+ismaller)/2 ; ltrial=lkpg1_sorted(itrial)
211        if((ltrial-lk2)>tol12)then
212          ilarger=itrial ; llarger=ltrial
213        else if((ltrial-lk2)<-tol12)then
214          ismaller=itrial ; lsmaller=ltrial
215        else
216          ismaller=itrial ; lsmaller=ltrial
217          ilarger=itrial ; llarger=ltrial
218        end if
219      end do
220      itrial=ismaller
221      if(abs(llarger-lk2)<abs(lsmaller-lk2)-tol12)itrial=ilarger
222      if(itrial==0)itrial=ilarger
223      ismaller=itrial ; ilarger=itrial
224 !    write(std_out,*)' listkk : starting search at itrial=',itrial
225 
226      dksqmn=huge(one)
227 
228 !    The ii index is dummy. This avoids an infinite loop.
229      do ii=1,l3*nkpt1
230 !      do ikpt1=1,nkpt1
231 
232 !      If the difference in length between the trial vector and the target vector is bigger
233 !      than the already achieved distance, the search is finished ...
234        ldiff=abs(lkpg1_sorted(itrial)-lk2)
235 
236 
237 !      DEBUG
238 !      write(std_out,*)' listkk : ii,itrial,lkpg1_sorted(itrial),lk2,ldiff,dksqmn=',ii,itrial,lkpg1_sorted(itrial),lk2,ldiff,dksqmn
239 !      ENDDEBUG
240        if(ldiff**2>dksqmn+tol8)exit
241 
242 !      If this k-point has already been examined in a previous batch, skip it
243 !      First, compute the minimum of the difference of length of the sets of associated vectors thanks to Umklapp vectors
244 !      with the target vector
245        ikpt1=(isort(itrial)-1)/l3+1
246        min_l=minval(abs(lkpg1((ikpt1-1)*l3+1:(ikpt1-1)*l3+l3)-lk2))
247 !      Then compare with the current ldiff
248 
249 !      DEBUG
250 !      write(std_out,*)' listkk : ikpt1,min_l,ldiff=',ikpt1,min_l,ldiff
251 !      ENDDEBUG
252 
253        if(min_l > ldiff-tol12)then
254 
255 !        Now, will examine the trial vector, and the symmetric ones
256 !MG FIXME:
257 ! Here there's a possible problem with the order of symmetries because
258 ! in symkpt, time-reversal is the innermost loop. This can create inconsistencies in the symmetry tables.
259          do itimrev=0,timrev_used
260            do isym=1,nsym_used
261 
262 !            Select magnetic characteristic of symmetries
263              if(isppol==1 .and. symafm(isym)==-1)cycle
264              if(isppol==2 .and. symafm(isym)==1)cycle
265 
266 !            Compute symmetric point to kpt1
267              if(usesym==1)then
268 !              original code only used transpose(symrel)
269 !              kpt1a(:)=symrel(1,:,isym)*kptns1(1,ikpt1)+&
270 !              &             symrel(2,:,isym)*kptns1(2,ikpt1)+&
271 !              &             symrel(3,:,isym)*kptns1(3,ikpt1)
272                if (present(use_symrec)) then
273                  if (use_symrec) then
274                    kpt1a(:) = MATMUL(symmat(:,:,isym),kptns1(:,ikpt1))
275                  else
276                    kpt1a(:) = MATMUL(TRANSPOSE(symmat(:,:,isym)),kptns1(:,ikpt1))
277                  end if
278                else
279                  kpt1a(:) = MATMUL(TRANSPOSE(symmat(:,:,isym)),kptns1(:,ikpt1))
280                end if
281                kpt1a(:)=(1-2*itimrev)*kpt1a(:)
282              else
283                kpt1a(:)=kptns1(:,ikpt1)
284              end if
285 
286 !            Compute difference with respect to kpt2, modulo a lattice vector
287              dk(:)=kptns2(:,ikpt2)-kpt1a(:)
288              if(usesym==1)then
289 !              The tolerance insure similar behaviour on different platforms
290 !              XG120418 : Actually, *assumes* that the closest point will have reduced
291 !              coordinates differing by less than 1/2 . There might be elongated
292 !              cells where this is not correct ...
293                dkint(:)=nint(dk(:)+tol12)
294                dk(:)=dk(:)-dkint(:)
295              else
296                dkint(:)=0
297              end if
298 
299 !            Compute norm of the difference vector, and update kpt1 if better.
300              dksq=gmet(1,1)*dk(1)**2+gmet(2,2)*dk(2)**2+&
301 &             gmet(3,3)*dk(3)**2+two*(gmet(2,1)*dk(2)*dk(1)+&
302 &             gmet(3,2)*dk(3)*dk(2)+gmet(3,1)*dk(3)*dk(1))
303 
304              if (dksq<dksqmn+tol8) then
305 
306 !              If exactly the right point (without using symmetries neither umklapp vector), will exit the search
307 !              Note that in this condition, each coordinate is tested separately, without squaring. So, it is a much stronger
308 !              condition than dksqmn<tol12
309                if(sum(abs(kptns2(:,ikpt2)-kptns1(:,ikpt1)))<3*tol12)then
310                  ikpt2_done=1
311                end if
312 
313 !              Update in three cases : either if succeeded to have exactly the vector, or the distance is better,
314 !              or the distance is only slightly worsened so select the lowest itimrev, isym or ikpt1, in order to respect previous ordering
315                if(  ikpt2_done==1 .or. &
316 &               dksq+tol12<dksqmn .or. &
317 &               ( abs(dksq-dksqmn)<tol12 .and. &
318 &               ((itimrev<jtime) .or. &
319 &               (itimrev==jtime .and. isym<jsym) .or. &
320 &               (itimrev==jtime .and. isym==jsym .and. ikpt1<jkpt1))))then
321 
322                  dksqmn=dksq
323                  jkpt1=ikpt1
324                  jsym=isym
325                  jtime=itimrev
326                  jdkint(:)=dkint(:)
327 
328 !                DEBUG
329 !                write(std_out,*)' ikpt1,ikpt2=',ikpt1,ikpt2
330 !                write(std_out,*)' timrev_used=',timrev_used
331 !                write(std_out,*)' Succeeded to lower dskmn,ikpt2_done=',dksqmn,ikpt2_done
332 !                write(std_out,*)' ikpt1,isym,dkint(:),itimrev=',ikpt1,isym,dkint(:),itimrev
333 !                ka(:)=kpt1a(:)+dkint(:)
334 !                write(std_out,*)'        k1=',kpt1a(:)
335 !                write(std_out,*)'     dkint=',dkint(:)
336 !                write(std_out,*)' Actual k1=',ka(:)
337 !                write(std_out,*)'        k2=',kptns2(:,ikpt2)
338 !                kasq=gmet(1,1)*ka(1)**2+gmet(2,2)*ka(2)**2+&
339 !                &                  gmet(3,3)*ka(3)**2+two*(gmet(2,1)*ka(2)*ka(1)+&
340 !                &                  gmet(3,2)*ka(3)*ka(2)+gmet(3,1)*ka(3)*ka(1))
341 !                write(std_out,*)' Actual k1sq=',kasq
342 !                ENDDEBUG
343                end if
344 
345              end if
346              if(ikpt2_done==1)exit
347 
348            end do ! isym
349            if(ikpt2_done==1)exit
350 
351          end do ! itimrev
352          if(ikpt2_done==1)exit
353 
354        end if
355 
356 !      Update the interval that has been explored
357        if(itrial<ismaller)ismaller=itrial
358        if(itrial>ilarger)ilarger=itrial
359 
360 !      Select the next index to be tried (preferably the smaller indices, but this is a bit arbitrary).
361 
362 !      DEBUG
363 !      write(std_out,*)' before choosing the next index :'
364 !      write(std_out,*)' ismaller,itrial,ilarger=',ismaller,itrial,ilarger
365 !      write(std_out,*)' lkpg1_sorted(ismaller-1),lk2,lkpg1_sorted(ilarger+1)=',lkpg1_sorted(ismaller-1),lk2,lkpg1_sorted(ilarger+1)
366 !      ENDDEBUG
367        if(ismaller>1 .and. ilarger<l3*nkpt1)then
368          if(abs(lkpg1_sorted(ismaller-1)-lk2)<abs(lkpg1_sorted(ilarger+1)-lk2)+tol12)then
369            itrial=ismaller-1
370          else
371            itrial=ilarger+1
372          end if
373        end if
374        if(ismaller==1 .and. ilarger<l3*nkpt1)itrial=ilarger+1
375        if(ismaller>1 .and. ilarger==l3*nkpt1)itrial=ismaller-1
376 !      if(ismaller==1 .and. ilarger==l3*nkpt1), we are done with the loop !
377 
378      end do ! ikpt1
379 
380      indkk(ikpt2+(isppol-1)*nkpt2,1)=jkpt1
381      indkk(ikpt2+(isppol-1)*nkpt2,2)=jsym
382      indkk(ikpt2+(isppol-1)*nkpt2,3:5)=jdkint(:)
383      indkk(ikpt2+(isppol-1)*nkpt2,6)=jtime
384      dksqmax=max(dksqmax,dksqmn)
385 
386      if(dksqmn<-tol12)then
387        write(message, '(a,es16.6)' )'  The minimum square of dk has negative norm: dksqmn=',dksqmn
388        MSG_BUG(message)
389      end if
390 
391 !    DEBUG
392 !    write(std_out,'(a,i6,i2,2x,i6,5i3,es24.14)' )' listkk: ikpt2,isppol,indkk(ikpt2+(isppol-1)*nkpt2,:)=',ikpt2,isppol,indkk(ikpt2+(isppol-1)*nkpt2,:),dksqmn
393 !    if(nkpt1==17)stop
394 !    ENDDEBUG
395 
396    end do ! ikpt2
397  end do ! isppol
398 
399  ABI_DEALLOCATE(isort)
400  ABI_DEALLOCATE(lkpg1)
401  ABI_DEALLOCATE(lkpg1_sorted)
402 
403  call timab(1021,2,tsec)
404 
405 end subroutine listkk