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-09-21 13:49:52 Functions: 71.4 % 7 5

            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