LCOV - code coverage report
Current view: top level - src/61_occeig - m_fstab.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.0 % 202 192
Test Date: 2026-11-10 14:34:30 Functions: 71.4 % 7 5
Branches: 61.7 % 554 342

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_fstab
       2                 :             : !! NAME
       3                 :             : !!  m_fstab
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  Tools for the management of a set of Fermi surface k-points.
       7                 :             : !!
       8                 :             : !! COPYRIGHT
       9                 :             : !!  Copyright (C) 2008-2026 ABINIT group (MG, MVer)
      10                 :             : !!  This file is distributed under the terms of the
      11                 :             : !!  GNU General Public License, see ~abinit/COPYING
      12                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13                 :             : !!
      14                 :             : !! SOURCE
      15                 :             : 
      16                 :             : #if defined HAVE_CONFIG_H
      17                 :             : #include "config.h"
      18                 :             : #endif
      19                 :             : 
      20                 :             : #include "abi_common.h"
      21                 :             : 
      22                 :             : module m_fstab
      23                 :             : 
      24                 :             :  use defs_basis
      25                 :             :  use m_abicore
      26                 :             :  use m_xmpi
      27                 :             :  use m_errors
      28                 :             :  use m_krank
      29                 :             :  use m_htetra
      30                 :             :  use m_ebands
      31                 :             :  use m_crystal
      32                 :             :  use m_dtset
      33                 :             : 
      34                 :             :  use m_time,           only : cwtime, cwtime_report
      35                 :             :  use m_fstrings,       only : itoa, sjoin, ktoa
      36                 :             :  use m_numeric_tools,  only : bisect
      37                 :             :  use m_matrix,         only : matr3inv
      38                 :             :  use m_special_funcs,  only : gaussian
      39                 :             :  use m_kpts,           only : kpts_timrev_from_kptopt, smpbz, kpts_map
      40                 :             : 
      41                 :             :  implicit none
      42                 :             : 
      43                 :             :  private
      44                 :             : !!***
      45                 :             : 
      46                 :             : !!****t* m_fstab/fstab_t
      47                 :             : !! NAME
      48                 :             : !! fstab_t
      49                 :             : !!
      50                 :             : !! FUNCTION
      51                 :             : !!  Tables with the correspondence between k-points on the Fermi surface (FS) and k-points
      52                 :             : !!  in the IBZ (i.e. the k-points found in ebands_t).
      53                 :             : !!  We use `nsppol` fstab_t objects to account for spin polarization and possibly different
      54                 :             : !!  number of bands crossing the Fermi level.
      55                 :             : !!
      56                 :             : !! SOURCE
      57                 :             : 
      58                 :             :  type,public :: fstab_t
      59                 :             : 
      60                 :             :    integer :: spin = -1
      61                 :             :     ! Spin index
      62                 :             : 
      63                 :             :    integer :: nkfs = -1
      64                 :             :     ! Number of k-points on the Fermi-surface in the full BZ.
      65                 :             : 
      66                 :             :    integer :: nktot = -1
      67                 :             :    !integer :: nkbz = -1
      68                 :             :     ! Total number of k-points in the initial mesh. Used to compute integrals in the BZ.
      69                 :             : 
      70                 :             :    integer :: nkibz = -1
      71                 :             :     ! Number of points in the IBZ
      72                 :             : 
      73                 :             :    integer :: bmin = -1, bmax = -1
      74                 :             :     ! Min and max band index included in the calculation.
      75                 :             :     ! Note that these values are obtained by taking the union over the k-points in the FS
      76                 :             :     ! For each k-point, we usually have a different number of states crossing eF given by bstart_cnt_ibz.
      77                 :             : 
      78                 :             :    integer :: maxnb = -1
      79                 :             :    ! Max number of bands on the FS i.e.: bmax - bmin + 1.
      80                 :             : 
      81                 :             :    integer :: eph_intmeth = 1
      82                 :             :    ! Integration method.
      83                 :             :    ! 1 for gaussian (including adaptive broadening if eph_fsmear is negative.
      84                 :             :    ! |2| for tetrahedra.
      85                 :             :    !     2 for the optimized tetrahedron method.
      86                 :             :    !    -2 for the linear tetrahedron method.
      87                 :             : 
      88                 :             :    integer :: nene = -1
      89                 :             :    ! Number of chemical potential values used for inelastic integration.
      90                 :             : 
      91                 :             :    real(dp) :: eph_fsmear
      92                 :             :    ! Gaussian broadening. Negative value activates adaptive gaussian broadening.
      93                 :             :    ! See https://journals.aps.org/prb/pdf/10.1103/PhysRevB.92.075405
      94                 :             : 
      95                 :             :    real(dp) :: min_smear = tol9
      96                 :             :    ! Used for the adaptive gaussian broadening: use min_smear if the broadening computed from the group velocity
      97                 :             :    ! is smaller than this value to avoid divergences in the gaussian.
      98                 :             : 
      99                 :             :    real(dp) :: enemin
     100                 :             :    ! Minimal chemical potential value used for inelastic integration.
     101                 :             : 
     102                 :             :    real(dp) :: deltaene
     103                 :             :    ! Chemical potential increment for inelastic integration.
     104                 :             : 
     105                 :             :    type(krank_t) :: krank
     106                 :             :    ! rank/inverse_rank pair for the k-points on the FS (kpts).
     107                 :             : 
     108                 :             :    integer,allocatable :: indkk_fs(:,:)
     109                 :             :    ! (6, nkfs)
     110                 :             :    ! Table giving the correspondence between a point in the FS-BZ and the IBZ:
     111                 :             :    !
     112                 :             :    !   indkk_fs(1,:)      Mapping FS-BZ --> k-points in the IBZ (taken from ebands_t)
     113                 :             :    !   indkk_fs(2,:)      The index of the symmetry S such that kfs = tim_sign * S(k_ibz) + G0
     114                 :             :    !   indkk_fs(3:5,:)    The reduced components of G0.
     115                 :             :    !   indkk_fs(6,:)      1 if time-reversal was used to generate the k-point, 0 otherwise
     116                 :             :    !
     117                 :             :    ! NB: The table is generated using the symrel convention and can therefore be used to
     118                 :             :    ! symmetrize wavefunctions in k-space.
     119                 :             : 
     120                 :             :    integer,allocatable :: bstart_cnt_ibz(:,:)
     121                 :             :     ! (2, nkibz)
     122                 :             :     ! The indices of the bands within the energy window (depends on fsk)
     123                 :             :     ! Note that we use the k-point index in the IBZ.
     124                 :             :     !
     125                 :             :     !   bstcnt(1, :) The index of the first band inside the energy window (start)
     126                 :             :     !   bstcnt(2, :) Number of bands on the FS (count)
     127                 :             : 
     128                 :             :    real(dp) :: klatt(3, 3)
     129                 :             :     ! Reciprocal of lattice vectors for full kpoint grid. Used by init_tetra
     130                 :             : 
     131                 :             :    real(dp) :: kmesh_cartvec(3,3)
     132                 :             :     ! vectors defining the k-mesh (stored as column vector in Cartesian coords.
     133                 :             :     ! Used to implement the adaptive gaussian broadening.
     134                 :             : 
     135                 :             :    real(dp),allocatable :: kpts(:,:)
     136                 :             :    ! (3, nkfs)
     137                 :             :    ! Reduced coordinates of the BZ k-points on the Fermi surface.
     138                 :             : 
     139                 :             :    real(dp),allocatable :: vk(:,:), vkq(:,:)
     140                 :             :    ! (3, mnb)
     141                 :             :    ! Velocities in cartesian coordinates. Used to implement the adaptive gaussian broadening
     142                 :             :    ! Values are filled by the caller (e.g. phgamma) inside the loop over k-points.
     143                 :             : 
     144                 :             :    real(dp),allocatable :: tetra_wtk(:,:)
     145                 :             :    ! (maxnb, nkibz)
     146                 :             :    ! Weights for FS integration with tetrahedron method
     147                 :             :    ! Note that the weights are dimensioned with nkibz
     148                 :             :    ! (1, :) corresponds to %bmin
     149                 :             : 
     150                 :             :    real(dp),allocatable :: tetra_wtk_ene(:,:,:)
     151                 :             :    ! (maxnb, nkibz, nene)
     152                 :             :    ! Weights for FS integration with tetrahedron method for all chemical potentials
     153                 :             :    ! Note that the weights are dimensioned with nkibz
     154                 :             :    ! (1, :) corresponds to %bmin
     155                 :             : 
     156                 :             :    real(dp),allocatable :: dbldelta_tetra_weights_kfs(:,:,:)
     157                 :             :    ! (maxnb, maxnb, nkfs)
     158                 :             :    ! (1, 1, :) corresponds to %bmin
     159                 :             : 
     160                 :             :  contains
     161                 :             : 
     162                 :             :    procedure :: free => fstab_free
     163                 :             :    ! Free memory.
     164                 :             : 
     165                 :             :    procedure :: findkg0 => fstab_findkg0
     166                 :             :    ! Find the index of the k-point on the FS
     167                 :             : 
     168                 :             :    procedure :: get_dbldelta_weights => fstab_get_dbldelta_weights
     169                 :             :    ! Compute weights for the integration of the double-delta.
     170                 :             : 
     171                 :             :  end type fstab_t
     172                 :             : 
     173                 :             :  public :: fstab_init    ! Initialize the object.
     174                 :             :  public :: fstab_print   ! Print the object
     175                 :             : !!***
     176                 :             : 
     177                 :             : !----------------------------------------------------------------------
     178                 :             : 
     179                 :             : contains  !============================================================
     180                 :             : !!***
     181                 :             : 
     182                 :             : !!****f* m_fstab/fstab_free
     183                 :             : !! NAME
     184                 :             : !!  fstab_free
     185                 :             : !!
     186                 :             : !! FUNCTION
     187                 :             : !!  Free memory
     188                 :             : !!
     189                 :             : !! SOURCE
     190                 :             : 
     191                 :           5 : subroutine fstab_free(fstab)
     192                 :             : 
     193                 :             : !Arguments ------------------------------------
     194                 :             :  class(fstab_t),intent(inout) :: fstab
     195                 :             : ! ************************************************************************
     196                 :             : 
     197                 :             :  ! integer
     198         [ +  - ]:           5 :  ABI_SFREE(fstab%indkk_fs)
     199         [ +  - ]:           5 :  ABI_SFREE(fstab%bstart_cnt_ibz)
     200                 :             : 
     201                 :             :  ! real
     202         [ +  - ]:           5 :  ABI_SFREE(fstab%kpts)
     203         [ +  - ]:           5 :  ABI_SFREE(fstab%vk)
     204         [ +  - ]:           5 :  ABI_SFREE(fstab%vkq)
     205         [ +  + ]:           5 :  ABI_SFREE(fstab%tetra_wtk)
     206         [ +  + ]:           5 :  ABI_SFREE(fstab%tetra_wtk_ene)
     207         [ +  + ]:           5 :  ABI_SFREE(fstab%dbldelta_tetra_weights_kfs)
     208                 :             : 
     209                 :             :  ! types
     210                 :           5 :  call fstab%krank%free()
     211                 :             : 
     212                 :           5 : end subroutine fstab_free
     213                 :             : !!***
     214                 :             : 
     215                 :             : !----------------------------------------------------------------------
     216                 :             : 
     217                 :             : !!****f* m_fstab/fstab_init
     218                 :             : !! NAME
     219                 :             : !!  fstab_init
     220                 :             : !!
     221                 :             : !! FUNCTION
     222                 :             : !!  Initialize the tables for the FS integration.
     223                 :             : !!
     224                 :             : !! INPUTS
     225                 :             : !!  ebands<ebands_t>=The object describing the band structure.
     226                 :             : !!  cryst<crystal_t>=Info on the crystalline structure.
     227                 :             : !!  dtset:
     228                 :             : !!    eph_fsewin=Energy window in Hartree. Only states in [efermi-fsewin, efermi+fsewin] are included.
     229                 :             : !!    eph_intmeth=Flag selecting the integration method.
     230                 :             : !!    kptrlatt(3,3)=k-point lattice specification
     231                 :             : !!    nshiftk= number of shift vectors.
     232                 :             : !!    shiftk(3,nshiftk)=shift vectors for k point generation
     233                 :             : !!  comm=MPI communicator.
     234                 :             : !!
     235                 :             : !! OUTPUT
     236                 :             : !!  fstab(nsppol)=Tables with the correspondence between points of the Fermi surface (FS)
     237                 :             : !!     and the k-points in ebands_t.
     238                 :             : !!  tetra: Tetrahedron object.
     239                 :             : !!
     240                 :             : !! TODO
     241                 :             : !!  Use a different algorithm to select k-points if tetra. First compute tetra weights
     242                 :             : !!  then k-points contributing to FS integrals are selected according to some threshold.
     243                 :             : !!
     244                 :             : !! SOURCE
     245                 :             : 
     246   [ +  +  -  +  :          15 : subroutine fstab_init(fstab, ebands, cryst, dtset, tetra, comm)
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          +  +  -  +  -  
          +  -  +  -  +  
          -  -  -  -  -  
             +  -  -  -  
                      - ]
     247                 :             : 
     248                 :             : !Arguments ------------------------------------
     249                 :             : !scalars
     250                 :             :  type(ebands_t),intent(in) :: ebands
     251                 :             :  type(crystal_t),intent(in) :: cryst
     252                 :             :  type(dataset_type),intent(in) :: dtset
     253                 :             :  type(htetra_t),intent(out) :: tetra
     254                 :             :  integer,intent(in) :: comm
     255                 :             : !arrays
     256                 :             :  type(fstab_t),target,intent(out) :: fstab(ebands%nsppol)
     257                 :             : 
     258                 :             : !Local variables-------------------------------
     259                 :             : !scalars
     260                 :             :  integer,parameter :: option0 = 0, brav1 = 1, bcorr0 = 0
     261                 :             :  integer :: nkfs,spin,band,nband_k,i1,i2,ib,blow,ik_bz,ik_ibz,nkibz
     262                 :             :  integer :: ik,mkpt,nkbz,ierr, nene,ifermi
     263                 :             :  real(dp),parameter :: max_occ1 = one
     264                 :             :  real(dp) :: elow,ehigh,ebis,enemin,enemax,deltaene,cpu,wall,gflops
     265                 :             :  logical :: in_win
     266                 :             :  character(len=80) :: errstr
     267                 :             :  character(len=5000) :: msg
     268                 :             :  type(fstab_t),pointer :: fs
     269                 :           5 :  type(krank_t) :: krank
     270                 :             : !arrays
     271                 :             :  integer :: kptrlatt(3,3)
     272                 :           5 :  integer,allocatable :: full2ebands(:,:),bz2ibz(:), fs2bz(:),indkk(:,:) !,fs2ibz(:)
     273                 :             :  real(dp) :: rlatt(3,3), klatt(3,3)
     274                 :           5 :  real(dp),allocatable :: kbz(:,:), tmp_eigen(:),bdelta(:,:),btheta(:,:)
     275                 :             : ! *************************************************************************
     276                 :             : 
     277                 :           5 :  call cwtime(cpu, wall, gflops, "start")
     278                 :             : 
     279   [ +  +  +  +  :          80 :  if (any(cryst%symrel(:,:,1) /= identity_3d) .and. any(abs(cryst%tnons(:,1)) > tol10) ) then
          +  -  +  +  +  
                -  -  + ]
     280                 :           0 :    ABI_ERROR('The first symmetry is not the identity operator!')
     281                 :             :  end if
     282                 :             : 
     283                 :           5 :  nkibz = ebands%nkpt
     284   [ +  +  +  + ]:          65 :  kptrlatt = dtset%kptrlatt
     285                 :             :  !call kpts_ibz_from_kptrlatt(cryst, kptrlatt, ebands%kptopt, dtset%nshiftk, dtset%shiftk, &
     286                 :             :  ! nkibz, kibz, wtk, nkbz, kbz, &
     287                 :             :  ! new_kptrlatt, new_shiftk)  ! Optional
     288                 :             : 
     289                 :             :  ! Call smpbz to get the full grid of k-points `kbz`
     290                 :             :  ! brav1=1 is able to treat all bravais lattices (same option used in getkgrid)
     291                 :             :  mkpt= kptrlatt(1,1)*kptrlatt(2,2)*kptrlatt(3,3) &
     292                 :             :    +kptrlatt(1,2)*kptrlatt(2,3)*kptrlatt(3,1) &
     293                 :             :    +kptrlatt(1,3)*kptrlatt(2,1)*kptrlatt(3,2) &
     294                 :             :    -kptrlatt(1,2)*kptrlatt(2,1)*kptrlatt(3,3) &
     295                 :             :    -kptrlatt(1,3)*kptrlatt(2,2)*kptrlatt(3,1) &
     296                 :           5 :    -kptrlatt(1,1)*kptrlatt(2,3)*kptrlatt(3,2)
     297                 :             : 
     298   [ -  +  +  -  :          15 :  ABI_MALLOC(kbz, (3, mkpt))
          +  -  +  -  -  
                +  -  + ]
     299                 :             : 
     300                 :           5 :  call smpbz(brav1, std_out, kptrlatt, mkpt, nkbz, dtset%nshiftk, option0, dtset%shiftk, kbz)
     301                 :             : 
     302                 :             :  ! Find correspondence BZ --> IBZ
     303                 :             :  ! Note that we use symrel so these tables can be used to symmetrize wavefunctions.
     304   [ -  +  +  -  :          15 :  ABI_MALLOC(indkk, (6, nkbz))
          +  -  +  -  -  
                +  -  + ]
     305                 :             : 
     306                 :           5 :  call krank%from_kptrlatt(ebands%nkpt, ebands%kptns, kptrlatt, compute_invrank=.False.)
     307                 :             : 
     308         [ -  + ]:           5 :  if (kpts_map("symrel", ebands%kptopt, cryst, krank, nkbz, kbz, indkk) /= 0) then
     309                 :             :    write(msg, '(10a)' ) &
     310                 :           0 :    'The WFK file cannot be used to start the present calculation ',ch10, &
     311                 :           0 :    'It was asked that the wavefunctions be accurate, but',ch10, &
     312                 :           0 :    'at least one of the k points could not be generated from a symmetrical one.',ch10, &
     313                 :           0 :    'Action: check your WFK file and k-point input variables',ch10, &
     314                 :           0 :    '        (e.g. kptopt or shiftk might be wrong in the present dataset or the preparatory one.'
     315                 :           0 :    ABI_ERROR(msg)
     316                 :             :  end if
     317                 :             : 
     318                 :           5 :  call krank%free()
     319                 :           5 :  call cwtime_report(" fstab_init%krank", cpu, wall, gflops)
     320                 :             : 
     321   [ -  +  +  -  :       17930 :  ABI_ICALLOC(full2ebands, (6, nkbz))
          -  +  -  +  +  
                +  +  + ]
     322                 :             : 
     323         [ +  + ]:        2565 :  do ik_bz=1,nkbz
     324                 :        2560 :    full2ebands(1, ik_bz) = indkk(1, ik_bz)      ! ik_ibz
     325                 :        2560 :    full2ebands(2, ik_bz) = indkk(2, ik_bz)      ! isym
     326         [ +  + ]:       10240 :    full2ebands(3:5, ik_bz) = indkk(3:5, ik_bz)  ! g0
     327                 :        2565 :    full2ebands(6, ik_bz) = indkk(6, ik_bz)      ! itimrev
     328                 :             :  end do
     329         [ -  + ]:           5 :  ABI_FREE(indkk)
     330                 :             : 
     331                 :             :  ! Select only the k-points in the BZ that are sufficiently close to the FS.
     332                 :             :  ! FIXME: Do not know why but lambda depends on eph_fsewin if gaussian.
     333         [ -  + ]:           5 :  ABI_CHECK(dtset%eph_fsewin > tol12, "dtset%eph_fsewin < tol12")
     334                 :           5 :  elow = ebands%fermie - dtset%eph_fsewin
     335                 :           5 :  ehigh = ebands%fermie + dtset%eph_fsewin
     336                 :           5 :  ebis = elow - abs(elow) * 0.001_dp
     337                 :             : 
     338                 :             :  ! Allocate workspace arrays.
     339                 :             :  !ABI_MALLOC(fs2ibz, (nkbz))
     340   [ -  +  +  -  :          15 :  ABI_MALLOC(fs2bz, (nkbz))
          +  -  +  -  -  
                +  -  + ]
     341                 :             : 
     342         [ +  + ]:          10 :  do spin=1,ebands%nsppol
     343                 :           5 :    fs => fstab(spin)
     344                 :           5 :    fs%spin = spin
     345   [ -  +  +  -  :          15 :    ABI_MALLOC(fs%bstart_cnt_ibz, (2, nkibz))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     346   [ +  +  +  + ]:         440 :    fs%bstart_cnt_ibz = -1
     347                 :             : 
     348                 :             :    ! Find k-points on the FS associated to this spin.
     349                 :           5 :    nkfs = 0
     350         [ +  + ]:        2565 :    do ik_bz=1,nkbz
     351                 :        2560 :      ik_ibz = full2ebands(1, ik_bz)
     352                 :        2560 :      nband_k = ebands%nband(ik_ibz + (spin-1)*nkibz)
     353                 :             : 
     354                 :        2560 :      blow = bisect(ebands%eig(:nband_k, ik_ibz, spin), ebis)
     355         [ -  + ]:        2560 :      if (blow == 0) blow = 1
     356                 :             :      !if (blow == nband_k .or. blow == 0) cycle ! out of range
     357                 :             :      !write(std_out,*)"here with blow: ", blow,nband_k
     358                 :             :      !write(std_out,*)"eig_blow, eig_max, elow, ehigh:", &
     359                 :             :      !                ebands%eig(blow, ik_ibz, spin), ebands%eig(nband_k, ik_ibz, spin), elow,ehigh
     360                 :             : 
     361                 :             :      in_win = .False.; i1 = huge(1); i2 = -1
     362         [ +  + ]:       14415 :      do band=blow,nband_k
     363                 :             :         !if (ebands%eig(band, ik_ibz, spin) > ehigh) exit
     364                 :             :         !write(std_out,*)band, ebands%eig(band, ik_ibz, spin) >= elow, ebands%eig(band, ik_ibz, spin) <= ehigh
     365   [ +  +  +  + ]:       14415 :         if (ebands%eig(band, ik_ibz, spin) >= elow .and. ebands%eig(band, ik_ibz, spin) <= ehigh) then
     366                 :         690 :           in_win = .True.; i1 = min(i1, band); i2 = max(i2, band)
     367                 :             :         end if
     368                 :             :      end do
     369                 :             : 
     370         [ +  + ]:        2565 :      if (in_win) then
     371                 :             :        ! Add this k-point and the corresponding bands.
     372                 :             :        !write(std_out,*)"in win"
     373                 :         690 :        nkfs = nkfs + 1
     374                 :             :        !fs2ibz(nkfs) = ik_ibz
     375                 :         690 :        fs2bz(nkfs) = ik_bz
     376   [ +  +  +  +  :         750 :        if (any(fs%bstart_cnt_ibz(:, ik_ibz) /= [-1, -1])) then
                   +  + ]
     377   [ +  +  +  -  :        1980 :          ABI_CHECK(all(fs%bstart_cnt_ibz(:, ik_ibz) == [i1, i2-i1+1]), "bstart_cnt_ibz!")
                   -  + ]
     378                 :             :        end if
     379         [ +  + ]:        2070 :        fs%bstart_cnt_ibz(:, ik_ibz) = [i1, i2-i1+1]
     380                 :             :      end if
     381                 :             :    end do ! ik_bz
     382                 :             : 
     383                 :             :    ! Build fstab_t for this spin.
     384                 :           5 :    fs%nkibz = nkibz; fs%nkfs = nkfs; fs%nktot = nkbz
     385   [ -  +  +  -  :          15 :    ABI_MALLOC(fs%kpts, (3, nkfs))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     386   [ -  +  +  -  :          15 :    ABI_MALLOC(fs%indkk_fs, (6, nkfs))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     387         [ +  + ]:         695 :    do ik=1,nkfs
     388                 :             :      !ik_ibz = fs2ibz(ik)
     389                 :         690 :      ik_bz = fs2bz(ik)
     390         [ +  + ]:        2760 :      fs%kpts(:,ik) = kbz(:, ik_bz)
     391         [ +  + ]:        4835 :      fs%indkk_fs(:, ik) = full2ebands(:, ik_bz)
     392                 :             :    end do
     393                 :             : 
     394                 :             :    ! Define band indices enclosing states on the FS.
     395                 :             :    ! Note that we need all k-points for a given band when computing weights with tetrahedron.
     396                 :             :    ! This means that we have to be careful when selecting the weight associated to a given pair
     397                 :             :    ! (band_kq, kq), (band_k, k).
     398                 :             :    ! Then we have to rearrange the weights
     399                 :           5 :    fs%bmin = huge(1); fs%bmax = -huge(1)
     400         [ +  + ]:         150 :    do ik_ibz=1,nkibz
     401         [ +  + ]:         145 :      if (fs%bstart_cnt_ibz(1, ik_ibz) /= -1) then
     402                 :          30 :        fs%bmin = min(fs%bmin, fs%bstart_cnt_ibz(1,ik_ibz))
     403                 :             :      end if
     404         [ +  + ]:         150 :      if (fs%bstart_cnt_ibz(2, ik_ibz) /= -1) then
     405                 :          30 :        fs%bmax = max(fs%bmax, fs%bstart_cnt_ibz(1,ik_ibz) + fs%bstart_cnt_ibz(2,ik_ibz) - 1)
     406                 :             :      end if
     407                 :             :    end do
     408                 :             : 
     409                 :             :    !write(std_out,*)"bmin, bmax for tetra: ",fs%bmin, fs%bmax
     410   [ +  -  -  + ]:           5 :    ABI_CHECK(fs%bmin /= huge(1) .and. fs%bmax /= -huge(1), "No point on the Fermi surface!")
     411                 :           5 :    fs%maxnb = fs%bmax - fs%bmin + 1
     412                 :             : 
     413                 :             :    ! DEBUG: use same number of bands for each k-point on the FS.
     414                 :             :    !do ik_ibz=1,nkibz
     415                 :             :    !  if (fs%bstart_cnt_ibz(1, ik_ibz) /= -1) then
     416                 :             :    !    fs%bstart_cnt_ibz(1, ik_ibz) = fs%bmin
     417                 :             :    !    fs%bstart_cnt_ibz(2, ik_ibz) = fs%maxnb
     418                 :             :    !  end if
     419                 :             :    !end do
     420                 :             : 
     421   [ -  +  +  -  :          55 :    ABI_CALLOC(fs%vk, (3, fs%maxnb))
          +  -  +  -  -  
          +  -  +  -  +  
             +  +  +  + ]
     422   [ -  +  +  -  :          50 :    ABI_CALLOC(fs%vkq, (3, fs%maxnb))
          -  +  -  +  -  
             +  +  +  +  
                      + ]
     423                 :             : 
     424                 :          10 :    call fs%krank%init(nkfs, fs%kpts)
     425                 :             :  end do ! spin
     426                 :             : 
     427                 :           5 :  call cwtime_report(" fstab_init%fs_build:", cpu, wall, gflops)
     428                 :             : 
     429                 :             :  ! fix window around fermie for tetrahedron or gaussian weight calculation
     430                 :             :  ! this is spin independent
     431                 :           5 :  nene = 100 ! TODO: make this variable and maybe temperature dependent???
     432                 :           5 :  deltaene = two * dtset%eph_fsewin / dble(nene-1)
     433                 :           5 :  ifermi = int(nene / 2)
     434                 :           5 :  enemin = ebands%fermie - dble(ifermi-1)*deltaene
     435                 :           5 :  enemax = enemin + dble(nene-1)*deltaene
     436                 :             : 
     437   [ +  +  +  + ]:          65 :  rlatt = kptrlatt
     438                 :           5 :  call matr3inv(rlatt, klatt)
     439                 :             : 
     440                 :             :  ! Setup FS integration
     441         [ +  + ]:          10 :  do spin=1,ebands%nsppol
     442                 :           5 :    fs => fstab(spin)
     443                 :           5 :    fs%nene = nene
     444                 :           5 :    fs%enemin = enemin
     445                 :           5 :    fs%deltaene = deltaene
     446                 :           5 :    fs%eph_intmeth = dtset%eph_intmeth
     447                 :           5 :    fs%eph_fsmear = dtset%eph_fsmear
     448                 :             : 
     449   [ +  +  +  + ]:          65 :    fs%klatt = klatt
     450         [ +  + ]:          20 :    fs%kmesh_cartvec(:, 1) = cryst%gprimd(:,1)*klatt(1,1) + cryst%gprimd(:,2)*klatt(2,1) + cryst%gprimd(:,3)*klatt(3,1)
     451         [ +  + ]:          20 :    fs%kmesh_cartvec(:, 2) = cryst%gprimd(:,1)*klatt(1,2) + cryst%gprimd(:,2)*klatt(2,2) + cryst%gprimd(:,3)*klatt(3,2)
     452         [ +  + ]:          25 :    fs%kmesh_cartvec(:, 3) = cryst%gprimd(:,1)*klatt(1,3) + cryst%gprimd(:,2)*klatt(2,3) + cryst%gprimd(:,3)*klatt(3,3)
     453                 :             :    ! TODO: It seems that two_pi is not needed here!
     454                 :             :    !fs%kmesh_cartvec = two_pi * fs%kmesh_cartvec
     455                 :             :    !do i1=1,3
     456                 :             :    !  write(std_out, *)"klatt:", klatt(:, i1)
     457                 :             :    !  write(std_out, *)"gprimd:", cryst%gprimd(:, i1)
     458                 :             :    !  write(std_out, *)"cartvec:", fs%kmesh_cartvec(:, i1)
     459                 :             :    !end do
     460                 :             :  end do
     461                 :             : 
     462   [ -  +  +  -  :          10 :  ABI_MALLOC(bz2ibz, (nkbz))
             -  +  -  + ]
     463   [ -  +  +  + ]:        2570 :  bz2ibz = full2ebands(1, :)
     464                 :           5 :  call tetra%init(bz2ibz, cryst%gprimd, klatt, kbz, nkbz, ebands%kptns, nkibz, ierr, errstr, comm)
     465         [ -  + ]:           5 :  ABI_CHECK(ierr == 0, errstr)
     466         [ -  + ]:           5 :  ABI_FREE(bz2ibz)
     467                 :             : 
     468         [ +  + ]:           5 :  if (abs(dtset%eph_intmeth) == 2) then
     469                 :             :    ! TODO: compute weights on the fly to reduce memory? nene should be set to zero if not used!
     470   [ -  +  +  -  :           6 :    ABI_MALLOC(tmp_eigen, (nkibz))
          +  -  +  -  -  
                +  -  + ]
     471   [ -  +  +  -  :           6 :    ABI_MALLOC(btheta, (nene, nkibz))
          +  -  +  -  -  
                +  -  + ]
     472   [ -  +  +  -  :           4 :    ABI_MALLOC(bdelta, (nene, nkibz))
             -  +  -  + ]
     473                 :             : 
     474         [ +  + ]:           4 :    do spin=1,ebands%nsppol
     475                 :           2 :      fs => fstab(spin)
     476                 :             : 
     477                 :             :      ! Allocate tables used to store tetrahedron weights.
     478   [ -  +  +  -  :        1942 :      ABI_CALLOC(fs%dbldelta_tetra_weights_kfs, (fs%maxnb, fs%maxnb, fs%nkfs))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
          +  -  +  +  +  
             +  +  +  + ]
     479   [ -  +  +  -  :         182 :      ABI_CALLOC(fs%tetra_wtk, (fs%maxnb, nkibz))
          -  +  +  -  +  
          -  +  -  -  +  
          -  +  -  +  +  
                +  +  + ]
     480   [ -  +  +  -  :       17610 :      ABI_CALLOC(fs%tetra_wtk_ene, (fs%maxnb, nkibz, fs%nene))
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
          +  -  +  +  +  
             +  +  +  + ]
     481                 :             : 
     482         [ +  + ]:           8 :      do band=fs%bmin,fs%bmax
     483                 :             :        ! Get the contribution of this band
     484   [ +  -  -  +  :         124 :        tmp_eigen = ebands%eig(band, :nkibz, spin)
             -  -  +  + ]
     485                 :             : 
     486                 :             :        ! Calculate general integration weights at each irred kpoint
     487                 :             :        ! as in Blochl et al PRB 49 16223 [[cite:Bloechl1994a]]
     488                 :             :        call tetra%blochl_weights(tmp_eigen, enemin, enemax, max_occ1, fs%nene, nkibz, &
     489                 :           4 :          bcorr0, btheta, bdelta, xmpi_comm_self)
     490                 :             : 
     491                 :             :        ! Save weights in the correct position.
     492                 :           4 :        ib = band - fs%bmin + 1
     493         [ +  + ]:         122 :        do ik_ibz=1,nkibz
     494                 :         116 :          fs%tetra_wtk(ib, ik_ibz) = bdelta(ifermi, ik_ibz) * nkibz
     495         [ +  + ]:       11720 :          fs%tetra_wtk_ene(ib, ik_ibz, 1:fs%nene) = bdelta(1:fs%nene, ik_ibz) * nkibz
     496                 :             :        end do
     497                 :             :      end do ! band
     498                 :             :    end do ! spin
     499                 :             : 
     500         [ -  + ]:           2 :    ABI_FREE(tmp_eigen)
     501         [ -  + ]:           2 :    ABI_FREE(btheta)
     502         [ -  + ]:           2 :    ABI_FREE(bdelta)
     503                 :             :  end if
     504                 :             : 
     505                 :             :  !ABI_FREE(fs2ibz)
     506         [ -  + ]:           5 :  ABI_FREE(fs2bz)
     507         [ -  + ]:           5 :  ABI_FREE(kbz)
     508         [ -  + ]:           5 :  ABI_FREE(full2ebands)
     509                 :             : 
     510                 :           5 :  call cwtime_report(" fstab_init%fs_weights:", cpu, wall, gflops)
     511   [ +  -  +  + ]:          15 :  if (xmpi_comm_rank(comm) == 0) call fstab_print(fstab, [std_out, ab_out])
     512                 :             : 
     513   [ -  +  -  +  :          25 : end subroutine fstab_init
                   -  + ]
     514                 :             : !!***
     515                 :             : 
     516                 :             : !----------------------------------------------------------------------
     517                 :             : 
     518                 :             : !!****f* m_fstab/fstab_findkg0
     519                 :             : !! NAME
     520                 :             : !!  fstab_findkg0
     521                 :             : !!
     522                 :             : !! FUNCTION
     523                 :             : !!  Return the index `ik_fs` of the k-point `kpt` in the FS-BZ. Return -1 if not found.
     524                 :             : !!
     525                 :             : !! INPUTS
     526                 :             : !!  kpt(3)=K-point in reduced coordinates
     527                 :             : !!
     528                 :             : !! OUTPUT
     529                 :             : !!   g0=Reciprocal lattice vector such that kpt = fstab%kpts(:, ik_fs) + g0
     530                 :             : !!
     531                 :             : !! SOURCE
     532                 :             : 
     533                 :        9792 : integer function fstab_findkg0(fstab, kpt, g0) result(ik_fs)
     534                 :             : 
     535                 :             : !Arguments ------------------------------------
     536                 :             : !scalars
     537                 :             :  class(fstab_t),intent(in) :: fstab
     538                 :             : !arrays
     539                 :             :  integer,intent(out) :: g0(3)
     540                 :             :  real(dp),intent(in) :: kpt(3)
     541                 :             : ! *************************************************************************
     542                 :             : 
     543                 :        9792 :  ik_fs = fstab%krank%get_index(kpt)
     544         [ +  + ]:        9792 :  if (ik_fs /= -1) then
     545         [ +  + ]:       17600 :    g0 = nint(kpt - fstab%kpts(:, ik_fs))
     546                 :             :  else
     547         [ +  + ]:       21568 :    g0 = huge(1)
     548                 :             :  end if
     549                 :             : 
     550                 :        9792 : end function fstab_findkg0
     551                 :             : !!***
     552                 :             : 
     553                 :             : !----------------------------------------------------------------------
     554                 :             : 
     555                 :             : !!****f* m_fstab/fstab_get_dbldelta_weights
     556                 :             : !! NAME
     557                 :             : !!  fstab_get_dbldelta_weights
     558                 :             : !!
     559                 :             : !! FUNCTION
     560                 :             : !!  Return the weights for the integration of the double-delta on the Fermi-surface
     561                 :             : !!
     562                 :             : !! INPUTS
     563                 :             : !!  ebands<ebands_type>=GS band structure.
     564                 :             : !!  ik_ibz=Index of the k-point in the IBZ
     565                 :             : !!  spin=Spin index
     566                 :             : !!  nesting=Used in tetra. Set to 1 if tetra Weights cannot be computed with Tetrahedron due to nesting.
     567                 :             : !!   In this case, we fallback to adaptive gaussian.
     568                 :             : !!
     569                 :             : !! OUTPUT
     570                 :             : !!   wtk(fs%maxnb, fs%maxnb)=Weights for FS integration.
     571                 :             : !!
     572                 :             : !! SOURCE
     573                 :             : 
     574                 :        2864 : subroutine fstab_get_dbldelta_weights(fs, ebands, ik_fs, ik_ibz, ikq_ibz, spin, nesting, wtk)
     575                 :             : 
     576                 :             : !Arguments ------------------------------------
     577                 :             : !scalars
     578                 :             :  class(fstab_t),intent(in) :: fs
     579                 :             :  class(ebands_t),intent(in) :: ebands
     580                 :             :  integer,intent(in) :: ik_fs, ik_ibz, ikq_ibz, spin, nesting
     581                 :             : !arrays
     582                 :             :  real(dp),intent(out) :: wtk(fs%maxnb, fs%maxnb)
     583                 :             : 
     584                 :             : !Local variables-------------------------------
     585                 :             : !scalars
     586                 :             :  integer :: bstart_k, nband_k, bstart_kq, nband_kq, ib1, band1, ib2, band2, ii
     587                 :             :  logical :: use_adaptive
     588                 :             :  real(dp) :: g1, g2, sigma, abc(3)
     589                 :             : ! *************************************************************************
     590                 :             : 
     591                 :        2864 :  bstart_k = fs%bstart_cnt_ibz(1, ik_ibz); nband_k = fs%bstart_cnt_ibz(2, ik_ibz)
     592   [ +  -  -  + ]:        2864 :  ABI_CHECK(nband_k >= 1 .and. nband_k <= fs%maxnb, "Wrong nband_k")
     593                 :             : 
     594                 :        2864 :  bstart_kq = fs%bstart_cnt_ibz(1, ikq_ibz); nband_kq = fs%bstart_cnt_ibz(2, ikq_ibz)
     595   [ +  -  -  + ]:        2864 :  ABI_CHECK(nband_kq >= 1 .and. nband_kq <= fs%maxnb, "Wrong nband_kq")
     596                 :             : 
     597   [ +  +  +  + ]:       20048 :  wtk = zero
     598   [ +  +  +  + ]:        2864 :  if (fs%eph_intmeth == 1 .or. nesting /= 0) then
     599                 :             :    ! Gaussian method: constant or adaptive method from group velocities if eph_fsmear is negative.
     600                 :        1536 :    sigma = fs%eph_fsmear
     601   [ +  +  +  + ]:        1536 :    use_adaptive = fs%eph_fsmear < zero .or. abs(fs%eph_intmeth) == 2
     602         [ +  + ]:        3072 :    do ib2=1,nband_k
     603                 :        1536 :      band2 = ib2 + bstart_k - 1
     604         [ +  + ]:        1536 :      if (use_adaptive) then
     605         [ +  + ]:        4464 :        do ii=1,3
     606         [ +  + ]:       14508 :           abc(ii) = abs(dot_product(fs%vk(:, ib2), fs%kmesh_cartvec(:,ii)))
     607                 :             :        end do
     608   [ -  +  +  -  :        5580 :        sigma = max(maxval(abc), fs%min_smear)
                   +  + ]
     609                 :             :        !write(std_out, *)"sigma:", sigma * Ha_eV
     610                 :             :      end if
     611                 :        1536 :      g2 = gaussian(ebands%eig(band2, ik_ibz, spin) - ebands%fermie, sigma)
     612         [ +  + ]:        4608 :      do ib1=1,nband_kq
     613                 :        1536 :        band1 = ib1 + bstart_kq - 1
     614         [ +  + ]:        1536 :        if (use_adaptive) then
     615         [ +  + ]:        4464 :          do ii=1,3
     616         [ +  + ]:       14508 :            abc(ii) = abs(dot_product(fs%vkq(:, ib1), fs%kmesh_cartvec(:,ii)))
     617                 :             :          end do
     618   [ -  +  +  -  :        5580 :          sigma = max(maxval(abc), fs%min_smear)
                   +  + ]
     619                 :             :        end if
     620                 :        1536 :        g1 = gaussian(ebands%eig(band1, ikq_ibz, spin) - ebands%fermie, sigma)
     621                 :        3072 :        wtk(ib1, ib2) = (g1 * g2) / fs%nktot
     622                 :             :      end do
     623                 :             :    end do
     624                 :             : 
     625         [ +  - ]:        1328 :  else if (abs(fs%eph_intmeth) == 2) then
     626                 :             :    ! Tetrahedron method. Copy weights in the correct position.
     627         [ +  + ]:        2656 :    do ib2=1,nband_k
     628                 :        1328 :      band2 = ib2 + bstart_k - fs%bmin
     629         [ +  + ]:        3984 :      do ib1=1,nband_kq
     630                 :        1328 :        band1 = ib1 + bstart_kq - fs%bmin
     631                 :             :        ! libtetrabz_dbldelta seems to report weights in this order.
     632                 :        2656 :        wtk(ib1, ib2) = fs%dbldelta_tetra_weights_kfs(band1, band2, ik_fs)
     633                 :             :      end do
     634                 :             :    end do
     635                 :             : 
     636                 :             :  else
     637                 :           0 :    ABI_ERROR(sjoin("Wrong integration method:", itoa(fs%eph_intmeth)))
     638                 :             :  end if
     639                 :             : 
     640                 :        2864 : end subroutine fstab_get_dbldelta_weights
     641                 :             : !!***
     642                 :             : 
     643                 :             : !----------------------------------------------------------------------
     644                 :             : 
     645                 :             : !!****f* m_fstab/fstab_print
     646                 :             : !! NAME
     647                 :             : !!  fstab_print
     648                 :             : !!
     649                 :             : !! FUNCTION
     650                 :             : !!  Print info on the object.
     651                 :             : !!
     652                 :             : !! INPUTS
     653                 :             : !! units=unit numbers for output
     654                 :             : !! [header]=Header string.
     655                 :             : !! [prtvol]=verbosity level
     656                 :             : !!
     657                 :             : !! SOURCE
     658                 :             : 
     659                 :          10 : subroutine fstab_print(fstab, units, header, prtvol)
     660                 :             : 
     661                 :             : !Arguments ------------------------------------
     662                 :             : !scalars
     663                 :             :  class(fstab_t),target,intent(in) :: fstab(:)
     664                 :             :  integer,intent(in) :: units(:)
     665                 :             :  character(len=*),optional,intent(in) :: header
     666                 :             :  integer,optional,intent(in) :: prtvol
     667                 :             : 
     668                 :             : !Local variables-------------------------------
     669                 :             : !scalars
     670                 :             :  integer :: my_prtvol,spin
     671                 :             :  character(len=5000) :: msg
     672                 :             : ! *************************************************************************
     673                 :             : 
     674                 :           5 :  my_prtvol = 0; if (present(prtvol)) my_prtvol = prtvol
     675                 :             : 
     676                 :           5 :  msg = ' ==== Fermi surface info ==== '
     677   [ -  +  -  -  :           5 :  if (PRESENT(header)) msg=' ==== '//TRIM(ADJUSTL(header))//' ==== '
                   -  - ]
     678                 :           5 :  call wrtout(units, msg)
     679                 :             : 
     680                 :           8 :  select case (fstab(1)%eph_intmeth)
     681                 :             :  case (1)
     682         [ +  + ]:           3 :    if (fstab(1)%eph_fsmear > zero) then
     683                 :           1 :      write(msg,"(a,f5.1,a)")" FS integration done with gaussian method and broadening:", &
     684                 :           2 :        fstab(1)%eph_fsmear * Ha_eV, " (meV)"
     685                 :             :    else
     686                 :           2 :      write(msg,"(a)")" FS integration done with adaptive gaussian method"
     687                 :             :    end if
     688                 :             :  case (2)
     689                 :           2 :    write(msg,"(a)")" FS integration done with tetrahedron method"
     690                 :             :  case (-2)
     691                 :           0 :    write(msg,"(a)")" FS integration done with optimized tetrahedron method"
     692                 :             :  case default
     693   [ +  +  -  - ]:           5 :    ABI_ERROR(sjoin("Invalid value for eph_intmeth:", itoa(fstab(1)%eph_intmeth)))
     694                 :             :  end select
     695                 :             : 
     696                 :           5 :  call wrtout(units, msg)
     697                 :             : 
     698                 :           5 :  write(msg,"(a,i0)")" Total number of k-points in the full mesh: ",fstab(1)%nktot
     699                 :           5 :  call wrtout(units, msg)
     700                 :             :  !write(msg,"(a,f5.1)")" Energy window: ",fstab(1)%eph_fsewin * Ha_eV, " (eV)
     701                 :             :  !call wrtout(units, msg)
     702                 :             : 
     703         [ +  + ]:          10 :  do spin=1,size(fstab)
     704                 :           5 :    associate (fs => fstab(spin))
     705                 :           5 :    write(msg,"(a,i0)")" For spin: ",spin
     706                 :           5 :    call wrtout(units, msg)
     707                 :             :    write(msg,"(a,i0,a,f5.1,a)") &
     708                 :           5 :      "    Number of BZ k-points close to the Fermi surface: ",fs%nkfs," [", (100.0_dp * fs%nkfs) / fs%nktot, " %]"
     709                 :           5 :    call wrtout(units, msg)
     710                 :           5 :    write(msg,"(a,i0)")"    Maximum number of bands crossing the Fermi level: ",fs%maxnb
     711                 :           5 :    call wrtout(units, msg)
     712   [ +  +  +  + ]:         150 :    write(msg,"(2(a,i0))")"    min band: ", minval(fs%bstart_cnt_ibz(1,:), mask=fs%bstart_cnt_ibz(1,:) /= -1)
     713                 :           5 :    call wrtout(units, msg)
     714                 :           5 :    write(msg,"(2(a,i0))")"    Max band: ", maxval(fs%bstart_cnt_ibz(1,:) + fs%bstart_cnt_ibz(2,:) - 1, &
     715   [ +  +  +  + ]:         155 :                                                   mask=fs%bstart_cnt_ibz(1,:) /= -1)
     716                 :          10 :    call wrtout(units, msg)
     717                 :             :    end associate
     718                 :             :  end do
     719                 :             : 
     720         [ -  + ]:           5 : end subroutine fstab_print
     721                 :             : !!***
     722                 :             : 
     723   [ #  #  #  #  :           0 : end module m_fstab
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     724                 :             : !!***
        

Generated by: LCOV version 2.3-1