TABLE OF CONTENTS


ABINIT/newocc [ Functions ]

[ Top ] [ Functions ]

NAME

 newocc

FUNCTION

 Compute new occupation numbers at each k point,
 from eigenenergies eigen, according to the
 smearing scheme defined by occopt (smearing width tsmear and
 physical temperature tphysel),
 with the constraint of number of valence electrons per unit cell nelect.

COPYRIGHT

 Copyright (C) 1998-2017 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 .

INPUTS

  eigen(mband*nkpt*nsppol)=eigenvalues (input or init to large number), hartree
  spinmagntarget=if differ from -99.99_dp, fix the magnetic moment (in Bohr magneton)
  mband=maximum number of bands
  nband(nkpt)=number of bands at each k point
  nelect=number of electrons per unit cell
  nkpt=number of k points
  nspinor=number of spinorial components of the wavefunctions
  nsppol=1 for unpolarized, 2 for spin-polarized
  occopt=option for occupancies
  prtvol=control print volume and debugging output
  stmbias=if non-zero, compute occupation numbers for STM (non-zero around the Fermi energy)
   NOTE : in this case, only fermie and occ are meaningful outputs.
  tphysel="physical" electronic temperature with FD occupations
  tsmear=smearing width (or temperature)
  wtk(nkpt)=k point weights

OUTPUT

  doccde(maxval(nband(:))*nkpt*nsppol)=derivative of occupancies wrt
           the energy for each band and k point
  entropy= entropy associated with the smearing (adimensional)
  fermie= fermi energy (Hartree)
  occ(maxval(nband(:))*nkpt*nsppol)=occupancies for each band and k point

SIDE EFFECTS

PARENTS

      gstate,m_ebands,respfn,vtorho

CHILDREN

      getnel,timab,wrtout

SOURCE

 53 #if defined HAVE_CONFIG_H
 54 #include "config.h"
 55 #endif
 56 
 57 #include "abi_common.h"
 58 
 59 subroutine newocc(doccde,eigen,entropy,fermie,spinmagntarget,mband,nband,&
 60 &  nelect,nkpt,nspinor,nsppol,occ,occopt,prtvol,stmbias,tphysel,tsmear,wtk)
 61 
 62  use defs_basis
 63  use m_profiling_abi
 64  use m_errors
 65 
 66 !This section has been created automatically by the script Abilint (TD).
 67 !Do not modify the following lines by hand.
 68 #undef ABI_FUNC
 69 #define ABI_FUNC 'newocc'
 70  use interfaces_14_hidewrite
 71  use interfaces_18_timing
 72  use interfaces_61_occeig, except_this_one => newocc
 73 !End of the abilint section
 74 
 75  implicit none
 76 
 77 !Arguments ------------------------------------
 78 !scalars
 79  integer,intent(in) :: mband,nkpt,nspinor,nsppol,occopt,prtvol
 80  real(dp),intent(in) :: spinmagntarget,nelect,stmbias,tphysel,tsmear
 81  real(dp),intent(out) :: entropy,fermie
 82 !arrays
 83  integer,intent(in) :: nband(nkpt*nsppol)
 84  real(dp),intent(in) :: eigen(mband*nkpt*nsppol),wtk(nkpt)
 85  real(dp),intent(out) :: doccde(mband*nkpt*nsppol)
 86  real(dp),intent(inout) :: occ(mband*nkpt*nsppol) !vz_i
 87 
 88 !Local variables-------------------------------
 89  integer,parameter :: niter_max=120,nkpt_max=50,fake_unit=-666,option1=1
 90  integer :: cnt,cnt2,cnt3,ib,ii,ik,ikpt,is,isppol,nkpt_eff
 91  integer :: sign
 92  integer,allocatable :: nbandt(:)
 93  real(dp) :: dosdeltae,entropy_tmp,fermihi,fermilo,fermimid,fermimid_tmp
 94  real(dp) :: fermi_biased,maxocc
 95  real(dp) :: nelect_tmp,nelecthi,nelectlo,nelectmid,nelect_biased
 96  real(dp) :: entropyt(2),fermihit(2),fermilot(2),fermimidt(2),nelecthit(2)
 97  real(dp) :: nelectlot(2),nelectt(2),tsec(2)
 98  real(dp),allocatable :: doccdet(:),eigent(:),occt(:)
 99  character(len=500) :: message
100 
101 ! *************************************************************************
102 
103  DBG_ENTER("COLL")
104 
105  call timab(74,1,tsec)
106 
107 !Here treat the case where occopt does not correspond to a metallic occupation scheme
108  if (occopt<3 .or. occopt>8) then
109    write(message,'(a,i0,a)')' occopt= ',occopt,', a value not allowed in newocc.'
110    MSG_BUG(message)
111  end if ! test of metallic occopt
112 
113 !Check whether nband is a constant for all k point and spin-pol
114  do isppol=1,nsppol
115    do ikpt=1,nkpt
116      if(nband(ikpt+(isppol-1)*nkpt)/=nband(1))then
117        write(message,'(3a,i0,a,i0,a,i0,a)')&
118 &       'The number of bands must be the same for all k-points ',ch10,&
119 &       'but nband(1)= ',nband(1),' is different of nband(',&
120 &       ikpt+(isppol-1)*nkpt,') = ',nband(ikpt+(isppol-1)*nkpt),'.'
121        MSG_BUG(message)
122      end if
123    end do
124  end do
125 
126 !Check whether nelect is strictly positive
127  if(nelect<=zero)then
128    write(message,'(3a,es16.8,a)')&
129 &   'nelect must be a positive number, while ',ch10,&
130 &   'the calling routine ask nelect=',nelect,'.'
131    MSG_BUG(message)
132  end if
133 
134  maxocc=two/(nsppol*nspinor)
135 !Check whether nelect is coherent with nband (nband(1) is enough,
136 !since it was checked that nband is independent of k-point and spin-pol
137  if( nelect > nband(1)*nsppol*maxocc )then
138    write(message,'(3a,es16.8,a,i0,a,es16.8,a)' )&
139 &   'nelect must be smaller than nband*maxocc, while ',ch10,&
140 &   'the calling routine gives nelect= ',nelect,', nband= ',nband(1),' and maxocc= ',maxocc,'.'
141    MSG_BUG(message)
142  end if
143 
144 !Use bissection algorithm to find fermi energy
145 !This choice is due to the fact that it will always give sensible
146 !result (because the answer is bounded, even if the smearing function
147 !is non-monotonic (which is the case for occopt=4 or 6)
148 !Might speed up it, if needed !
149 
150 !Lowest and largest trial fermi energies, and corresponding number of electrons
151 !They are obtained from the smallest or largest eigenenergy, plus a range of
152 !energy that allows for complete occupation of all bands, or, on the opposite,
153 !for zero occupation of all bands (see getnel.f)
154  dosdeltae=zero  ! the DOS is not computed, with option=1
155  fermilo=minval(eigen(1:nband(1)*nkpt*nsppol))-6.001_dp*tsmear
156  if(occopt==3)fermilo=fermilo-24.0_dp*tsmear
157 
158  call getnel(doccde,dosdeltae,eigen,entropy,fermilo,maxocc,mband,nband,&
159 & nelectlo,nkpt,nsppol,occ,occopt,option1,tphysel,tsmear,fake_unit,wtk)
160 
161  fermihi=maxval(eigen(1:nband(1)*nkpt*nsppol))+6.001_dp*tsmear
162 !safety value
163  fermihi = min(fermihi, 1.e6_dp)
164  if(occopt==3)fermihi=fermihi+24.0_dp*tsmear
165 
166  call getnel(doccde,dosdeltae,eigen,entropy,fermihi,maxocc,mband,nband,&
167 & nelecthi,nkpt,nsppol,occ,occopt,option1,tphysel,tsmear,fake_unit,wtk)
168 
169 !Prepare fixed moment calculation
170  if(abs(spinmagntarget+99.99_dp)>1.0d-10)then
171    sign = 1
172    do is = 1, nsppol
173      fermihit(is) = fermihi
174      fermilot(is) = fermilo
175      nelectt(is) = half*(nelect+sign*spinmagntarget)
176      sign = -sign
177      nelecthit(is) = nelecthi
178      nelectlot(is) = nelectlo
179    end do
180  end if
181 
182 !If the target nelect is not between nelectlo and nelecthi, exit
183  if(nelect<nelectlo .or. nelect>nelecthi)then
184    write(message, '(a,a,a,a,d16.8,a,a,d16.8,a,d16.8,a,a,d16.8,a,d16.8)') ch10,&
185 &   ' newocc : ',ch10,&
186 &   '  The calling routine gives nelect=',nelect,ch10,&
187 &   '  The lowest bound is ',fermilo,', with nelect=',nelectlo,ch10,&
188 &   '  The highest bound is ',fermihi,', with nelect=',nelecthi
189    call wrtout(std_out,message,'COLL')
190 
191    write(message, '(11a)' )&
192 &   'In order to get the right number of electrons,',ch10,&
193 &   'it seems that the Fermi energy must be outside the range',ch10,&
194 &   'of eigenenergies, plus 6 or 30 times the smearing, which is strange.',ch10,&
195 &   'It might be that your number of bands (nband) corresponds to the strictly',ch10,&
196 &   'minimum number of bands to accomodate your electrons (so, OK for an insulator),',ch10,&
197 &   'while you are trying to describe a metal. In this case, increase nband, otherwise ...'
198    MSG_BUG(message)
199  end if
200 
201  if( abs(spinmagntarget+99.99_dp) < tol10 ) then
202 
203 !  Usual bissection loop
204    do ii=1,niter_max
205      fermimid=(fermihi+fermilo)*half
206 !    Produce nelectmid from fermimid
207      call getnel(doccde,dosdeltae,eigen,entropy,fermimid,maxocc,mband,nband,&
208 &     nelectmid,nkpt,nsppol,occ,occopt,option1,tphysel,tsmear,fake_unit,wtk)
209 !    write(std_out,'(a,es24.16,a,es24.16)' )' newocc : from fermi=',fermimid,', getnel gives nelect=',nelectmid
210      if(nelectmid>nelect*(one-tol14))then
211        fermihi=fermimid
212        nelecthi=nelectmid
213      end if
214      if(nelectmid<nelect*(one+tol14))then
215        fermilo=fermimid
216        nelectlo=nelectmid
217      end if
218      if( abs(nelecthi-nelectlo) <= nelect*two*tol14 .or. &
219 &     abs(fermihi-fermilo) <= tol14*abs(fermihi+fermilo) ) exit
220      if(ii==niter_max)then
221        write(message,'(a,i0,3a,es22.14,a,es22.14,a)')&
222 &       'It was not possible to find Fermi energy in ',niter_max,' bissections.',ch10,&
223 &       'nelecthi = ',nelecthi,', and nelectlo = ',nelectlo,'.'
224        MSG_BUG(message)
225      end if
226    end do ! End of bissection loop
227 
228    fermie=fermimid
229    write(message, '(a,f14.6,a,f14.6,a,a,i4)' ) &
230 &   ' newocc: new Fermi energy is ',fermie,' , with nelect=',nelectmid,ch10,&
231 &   '  Number of bissection calls =',ii
232    call wrtout(std_out,message,'COLL')
233 
234 !  Compute occupation numbers for prtstm/=0, close to the Fermi energy
235    if(abs(stmbias)>tol10)then
236      fermi_biased=fermie-stmbias
237      ABI_ALLOCATE(occt,(mband*nkpt*nsppol))
238      call getnel(doccde,dosdeltae,eigen,entropy,fermi_biased,maxocc,mband,nband,&
239 &     nelect_biased,nkpt,nsppol,occt,occopt,option1,tphysel,tsmear,fake_unit,wtk)
240      occ(:)=occ(:)-occt(:)
241      nelect_biased=abs(nelectmid-nelect_biased)
242 !    Here, arrange to have globally positive occupation numbers,
243 !    irrespective of the stmbias sign
244      if(-stmbias>tol10)occ(:)=-occ(:)
245      ABI_DEALLOCATE(occt)
246 
247      write(message,'(a,f14.6)')' newocc : the number of electrons in the STM range is nelect_biased=',nelect_biased
248      call wrtout(std_out,message,'COLL')
249 
250    end if
251 
252  else ! Calculations with a specified moment
253 
254 !  Bissection loop
255    cnt2=0
256    cnt3=0
257    entropy=zero
258    maxocc=one
259    ABI_ALLOCATE(doccdet,(nkpt*mband))
260    ABI_ALLOCATE(eigent,(nkpt*mband))
261    ABI_ALLOCATE(occt,(nkpt*mband))
262    ABI_ALLOCATE(nbandt,(nkpt))
263 
264    do is = 1, nsppol
265      nelect_tmp = nelectt(is)
266      fermihi = fermihit(is)
267      fermilo = fermilot(is)
268      nelecthi = nelecthit(is)
269      nelectlo = nelectlot(is)
270 !    DEBUG
271 !    write(std_out,'(a,i1,3(f8.4,1x))') "Spin, N(spin):", is, nelect, fermihi, fermilo
272 !    write(std_out,'(a,2(f8.4,1x))') "Hi, lo:", nelecthi, nelectlo
273 !    ENDDEBUG
274 
275      do ii=1,niter_max
276        fermimid_tmp=(fermihi+fermilo)/2.0_dp
277 !      temporary arrays
278        cnt = 0
279        do ik = 1, nkpt
280          nbandt(ik) = mband
281          do ib = 1, mband
282            cnt = cnt + 1
283            eigent(cnt) = eigen(cnt+cnt2)
284            occt(cnt) = occ(cnt+cnt2)
285            doccdet(cnt) = doccde(cnt+cnt2)
286          end do
287        end do
288 
289 !      Produce nelectmid from fermimid
290        call getnel(doccdet,dosdeltae,eigent,entropy_tmp,fermimid_tmp,maxocc,mband,nbandt,&
291 &       nelectmid,nkpt,1,occt,occopt,option1,tphysel,tsmear,fake_unit,wtk)
292        entropyt(is) = entropy_tmp
293        fermimidt(is) = fermimid_tmp
294        fermimid = fermimidt(is)
295 !      temporary arrays
296        cnt = 0
297        do ik = 1, nkpt
298          do ib = 1, mband
299            cnt = cnt + 1
300            occ(cnt+cnt2) = occt(cnt)
301            doccde(cnt+cnt2) = doccdet(cnt)
302          end do
303        end do
304 
305 !      DEBUG
306 !      write(std_out,'(a,es24.16,a,es24.16)' )&
307 !      &    ' newocc : from fermi=',fermimid,', getnel gives nelect=',nelectmid
308 !      ENDDEBUG
309 
310        if(nelectmid>=nelect_tmp)then
311          fermihi=fermimid_tmp
312          nelecthi=nelectmid
313        else
314          fermilo=fermimid_tmp
315          nelectlo=nelectmid
316        end if
317        if( abs(nelecthi-nelectlo) <= 1.0d-13 .or. abs(fermihi-fermilo) <= 0.5d-14*abs(fermihi+fermilo) ) exit
318 
319        if(ii==niter_max)then
320          write(message,'(a,i3,3a,es22.14,a,es22.14,a)')&
321 &         '  It was not possible to find Fermi energy in ',niter_max,' bissections.',ch10,&
322 &         '  nelecthi=',nelecthi,', and nelectlo=',nelectlo,'.'
323          MSG_BUG(message)
324        end if
325      end do ! End of bissection loop
326 
327      cnt2 = cnt2 + nkpt*mband
328      entropy = entropy + entropyt(is)
329      fermie=fermimid
330      write(message, '(a,i2,a,f14.6,a,f14.6,a,a,i4)' ) &
331 &     ' newocc : new Fermi energy for spin ', is, ' is ',fermie,' , with nelect=',nelectmid,ch10,&
332 &     '  Number of bissection calls =',ii
333      call wrtout(std_out,message,'COLL')
334 
335    end do ! spin
336 
337    ABI_DEALLOCATE(doccdet)
338    ABI_DEALLOCATE(eigent)
339    ABI_DEALLOCATE(nbandt)
340    ABI_DEALLOCATE(occt)
341 
342  end if !  End of logical on fixed moment calculations
343 
344 !write(std_out,*) "kT*Entropy:", entropy*tsmear
345 
346  nkpt_eff=nkpt
347  if(prtvol==0)nkpt_eff=min(nkpt_max,nkpt)
348 
349  if(nsppol==1)then
350    write(message, '(a,i0,a)' ) &
351 &   ' newocc : computed new occ. numbers for occopt= ',occopt,&
352 &   ' , spin-unpolarized case. '
353    call wrtout(std_out,message,'COLL')
354    do ikpt=1,nkpt_eff
355      write(message,'(a,i4,a)' ) ' k-point number ',ikpt,' :'
356      do ii=0,(nband(1)-1)/12
357        write(message,'(12f6.3)') &
358 &       occ(1+ii*12+(ikpt-1)*nband(1):min(12+ii*12,nband(1))+(ikpt-1)*nband(1))
359        call wrtout(std_out,message,'COLL')
360      end do
361    end do
362    if(nkpt/=nkpt_eff)then
363      call wrtout(std_out,' newocc: prtvol=0, stop printing more k-point information','COLL')
364    end if
365 
366 !  DEBUG
367 !  write(message, '(a)' ) &
368 !  &   ' newocc : corresponding derivatives are '
369 !  call wrtout(std_out,message,'COLL')
370 !  do ikpt=1,nkpt_eff
371 !  write(message,'(a,i4,a)' ) ' k-point number ',ikpt,' :'
372 !  do ii=0,(nband(1)-1)/12
373 !  write(message,'(12f6.1)') &
374 !  &    doccde(1+ii*12+(ikpt-1)*nband(1):min(12+ii*12,nband(1))+(ikpt-1)*nband(1))
375 !  call wrtout(std_out,message,'COLL')
376 !  end do
377 !  end do
378 !  if(nkpt/=nkpt_eff)then
379 !  write(message,'(a)') &
380 !  &    ' newocc : prtvol=0, stop printing more k-point informations'
381 !  call wrtout(std_out,message,'COLL')
382 !  end if
383 !  ENDDEBUG
384  else
385    write(message, '(a,i0,a,a)' ) &
386 &   ' newocc : computed new occupation numbers for occopt= ',occopt,&
387 &   ch10,'  (1) spin up   values  '
388    call wrtout(std_out,message,'COLL')
389    do ikpt=1,nkpt_eff
390      write(message,'(a,i0,a)' ) ' k-point number ',ikpt,':'
391      do ii=0,(nband(1)-1)/12
392        write(message,'(12f6.3)') &
393 &       occ(1+ii*12+(ikpt-1)*nband(1):min(12+ii*12,nband(1))+(ikpt-1)*nband(1))
394        call wrtout(std_out,message,'COLL')
395      end do
396    end do
397    if(nkpt/=nkpt_eff)then
398      call wrtout(std_out,'newocc: prtvol=0, stop printing more k-point information','COLL')
399    end if
400 
401    call wrtout(std_out,'  (2) spin down values  ','COLL')
402    do ikpt=1,nkpt_eff
403      do ii=0,(nband(1)-1)/12
404        write(message,'(12f6.3)') &
405 &       occ( 1+ii*12+(ikpt-1+nkpt)*nband(1) : &
406 &       min(12+ii*12,nband(1))+(ikpt-1+nkpt)*nband(1) )
407        call wrtout(std_out,message,'COLL')
408      end do
409    end do
410    if(nkpt/=nkpt_eff)then
411      call wrtout(std_out,' newocc: prtvol=0, stop printing more k-point information','COLL')
412    end if
413 
414  end if !  End choice based on spin
415 
416  call timab(74,2,tsec)
417 
418  DBG_EXIT("COLL")
419 
420 end subroutine newocc