LCOV - code coverage report
Current view: top level - shared/common/src/17_libtetra_ext - m_tetrahedron.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 49.9 % 705 352
Test Date: 2026-11-08 08:00:28 Functions: 46.7 % 15 7
Branches: 49.6 % 756 375

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_tetrahedron
       2                 :             : !! NAME
       3                 :             : !! m_tetrahedron
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  module for tetrahedron interpolation of DOS and similar quantities
       7                 :             : !!  depends on sort_tetra and on m_kpt_rank
       8                 :             : !!
       9                 :             : !! COPYRIGHT
      10                 :             : !!  Copyright (C) 2010-2026 ABINIT group (MJV)
      11                 :             : !!  This file is distributed under the terms of the
      12                 :             : !!  GNU General Public License, see ~abinit/COPYING
      13                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      14                 :             : !!
      15                 :             : !! TODO
      16                 :             : !!  1) Test carefully the case of degenerate tetrahedron
      17                 :             : !!  2) Change API so that we can pass the energy mesh instead of omega_min and omega_max
      18                 :             : !!  3) Add table ik_ibz --> tetra_list to avoid cycling inside big loop over ntetra
      19                 :             : !!  4) Add options to get only delta and/or theta ?
      20                 :             : !!
      21                 :             : !! SOURCE
      22                 :             : 
      23                 :             : #if defined HAVE_CONFIG_H
      24                 :             : #include "config.h"
      25                 :             : #endif
      26                 :             : 
      27                 :             : #include "libtetra.h"
      28                 :             : 
      29                 :             : module m_tetrahedron
      30                 :             : 
      31                 :             :   ! make sure stdout is defined, as libtetra.h needs it
      32                 :             :  use, intrinsic :: iso_fortran_env, only : stdin=>input_unit, &
      33                 :             :                                           stdout=>output_unit, &
      34                 :             :                                           stderr=>error_unit
      35                 :             :  USE_MEMORY_PROFILING
      36                 :             :  USE_MSG_HANDLING
      37                 :             :  use m_krank
      38                 :             :  USE_MPI
      39                 :             : #ifdef HAVE_LIBTETRA_ABINIT
      40                 :             :  use m_io_tools, only : open_file
      41                 :             :  use m_xmpi
      42                 :             :  use defs_basis, only : dp, zero, one, tol14, pi
      43                 :             : #elif
      44                 :             :  integer, parameter :: dp = kind(1.0d0)
      45                 :             :  real(dp), parameter :: tol14 = 1.d-14, zero = 0.d0, one = 1.d0
      46                 :             :  real(dp), parameter :: pi=3.141592653589793238462643383279502884197_dp
      47                 :             : #endif
      48                 :             : 
      49                 :             : implicit none
      50                 :             : 
      51                 :             : #if defined HAVE_MPI1
      52                 :             :  include 'mpif.h'
      53                 :             : #endif
      54                 :             : 
      55                 :             : private
      56                 :             : !!***
      57                 :             : 
      58                 :             : !!****t* m_tetrahedron/t_tetrahedron
      59                 :             : !! NAME
      60                 :             : !! t_tetrahedron
      61                 :             : !!
      62                 :             : !! FUNCTION
      63                 :             : !! tetrahedron geometry object
      64                 :             : !!
      65                 :             : !! SOURCE
      66                 :             : 
      67                 :             : type, public :: t_tetrahedron
      68                 :             : 
      69                 :             :   integer :: ntetra = 0
      70                 :             :   ! Number of tetrahedra
      71                 :             : 
      72                 :             :   real(dp)  :: vv
      73                 :             :   ! volume of the tetrahedra
      74                 :             : 
      75                 :             :   real(dp) :: klatt(3, 3)
      76                 :             :   ! reciprocal of lattice vectors for full kpoint grid
      77                 :             : 
      78                 :             :   integer,allocatable :: tetra_full(:,:,:)
      79                 :             :   !(4,2,ntetra)
      80                 :             :   ! For each tetra
      81                 :             :   !   (:,1,itetra) indices of the vertex in IBZ (symmetrical image)
      82                 :             :   !   (:,2,itetra) indices of the vertexes in the BZ
      83                 :             : 
      84                 :             :   integer,allocatable :: tetra_mult(:)
      85                 :             :   !(ntetra)
      86                 :             :   ! multiplicity of each irred tetrahedron
      87                 :             : 
      88                 :             :   integer,allocatable :: tetra_wrap(:,:,:)
      89                 :             :   !(3,4,ntetra)
      90                 :             :   ! flag to wrap tetrahedron summit into IBZ
      91                 :             : 
      92                 :             :   integer,allocatable :: ibz_tetra_count(:)
      93                 :             :   ! ibz_tetra_mapping(nkpt_ibz)
      94                 :             :   ! Number of tetrahedra associated to a point in the IBZ.
      95                 :             : 
      96                 :             :   integer,allocatable :: ibz_tetra_mapping(:,:)
      97                 :             :   ! ibz_tetra_mapping(nkpt_ibz, maxval(tetra%ibz_tetra_count)))
      98                 :             :   ! map ikbz to tetra index.
      99                 :             : 
     100                 :             : end type t_tetrahedron
     101                 :             : 
     102                 :             : public :: init_tetra               ! Initialize the object
     103                 :             :                                    ! See also the high-level interface tetra_from_kptrlatt provided by m_kpts.
     104                 :             : public :: get_tetra_weight         ! Calculate integration weights and their derivatives. shape (nkpt, nene).
     105                 :             : public :: tetra_blochl_weights     ! Same as in get_tetra_weight but weights have shape (nene, nkpt).
     106                 :             : public :: get_dbl_tetra_weight     ! Calculate integration weights for double tetrahedron integration of delta functions.
     107                 :             :                                    ! (NB these correspond to the derivative terms in normal tetrahedron).
     108                 :             : public :: destroy_tetra            ! Free memory.
     109                 :             : public :: tetra_write              ! Write text file (XML format) with tetra info.
     110                 :             : public :: tetralib_has_mpi         ! Return True if the library has been compiled with MPI support.
     111                 :             : public :: tetra_get_onewk          ! Calculate integration weights and their derivatives for a single k-point in the IBZ.
     112                 :             : public :: tetra_get_onewk_wvals    ! Similar to tetra_get_onewk_wvalsa but receives arbitrary list of frequency points.
     113                 :             : public :: tetra_get_onetetra_wvals ! Get weights for one tetrahedra with arbitrary list of frequency points
     114                 :             : !!***
     115                 :             : 
     116                 :             : contains
     117                 :             : !!***
     118                 :             : 
     119                 :             : !----------------------------------------------------------------------
     120                 :             : 
     121                 :             : !!****f* m_tetrahedron/destroy_tetra
     122                 :             : !! NAME
     123                 :             : !! destroy_tetra
     124                 :             : !!
     125                 :             : !! FUNCTION
     126                 :             : !! deallocate tetrahedra pointers if needed
     127                 :             : !!
     128                 :             : !! SOURCE
     129                 :             : 
     130                 :          11 : subroutine destroy_tetra (tetra)
     131                 :             : 
     132                 :             :  type(t_tetrahedron), intent(inout) :: tetra
     133                 :             : 
     134         [ +  + ]:          11 :  if (allocated(tetra%tetra_full)) then
     135                 :           4 :    TETRA_DEALLOCATE(tetra%tetra_full)
     136                 :             :  end if
     137         [ +  + ]:          11 :  if (allocated(tetra%tetra_mult)) then
     138                 :           4 :    TETRA_DEALLOCATE(tetra%tetra_mult)
     139                 :             :  end if
     140         [ +  + ]:          11 :  if (allocated(tetra%tetra_wrap)) then
     141                 :           4 :    TETRA_DEALLOCATE(tetra%tetra_wrap)
     142                 :             :  end if
     143         [ +  + ]:          11 :  if (allocated(tetra%ibz_tetra_count)) then
     144                 :           4 :    TETRA_DEALLOCATE(tetra%ibz_tetra_count)
     145                 :             :  end if
     146         [ +  + ]:          11 :  if (allocated(tetra%ibz_tetra_mapping)) then
     147                 :           4 :    TETRA_DEALLOCATE(tetra%ibz_tetra_mapping)
     148                 :             :  end if
     149                 :             : 
     150                 :          11 : end subroutine destroy_tetra
     151                 :             : !!***
     152                 :             : 
     153                 :             : !----------------------------------------------------------------------
     154                 :             : 
     155                 :             : !!****f* m_tetrahedron/init_tetra
     156                 :             : !! NAME
     157                 :             : !! init_tetra
     158                 :             : !!
     159                 :             : !! FUNCTION
     160                 :             : !! get tetrahedra characterized by apexes
     161                 :             : !!
     162                 :             : !! INPUTS
     163                 :             : !!  indkpt(nkpt_fullbz)=indexes of irred kpoints equivalent to kpt_fullbz
     164                 :             : !!  gprimd(3,3) = reciprocal space vectors
     165                 :             : !!  klatt(3,3)=reciprocal of lattice vectors for full kpoint grid
     166                 :             : !!  kpt_fullbz(3,nkpt_fullbz)=kpoints in full brillouin zone
     167                 :             : !!  nkpt_fullbz=number of kpoints in full brillouin zone
     168                 :             : !!  comm= MPI communicator
     169                 :             : !!
     170                 :             : !! OUTPUT
     171                 :             : !!  tetra%tetra_full(4,2,ntetra)=for each tetrahedron,
     172                 :             : !!     the different instances of the tetrahedron (fullbz kpoints)
     173                 :             : !!  tetra%tetra_mult(ntetra) = store multiplicity of each irred tetrahedron
     174                 :             : !!  tetra%tetra_wrap(3,4,ntetra) = store flag to wrap tetrahedron summit into IBZ
     175                 :             : !!  tetra%ntetra = final number of irred tetra (dimensions of tetra_* remain larger)
     176                 :             : !!  tetra%vv = tetrahedron volume divided by full BZ volume
     177                 :             : !!
     178                 :             : !! SOURCE
     179                 :             : 
     180   [ -  +  -  +  :           4 : subroutine init_tetra(indkpt, gprimd, klatt, kpt_fullbz, nkpt_fullbz, tetra, ierr, errorstring, comm)
             -  +  -  + ]
     181                 :             : 
     182                 :             : !Arguments ------------------------------------
     183                 :             : !scalars
     184                 :             :  integer,intent(in) :: nkpt_fullbz, comm
     185                 :             :  integer, intent(out) :: ierr
     186                 :             :  character(len=80), intent(out) :: errorstring
     187                 :             :  type(t_tetrahedron),intent(out) :: tetra
     188                 :             : !arrays
     189                 :             :  integer,intent(in) :: indkpt(nkpt_fullbz)
     190                 :             :  real(dp) ,intent(in) :: gprimd(3,3),klatt(3,3),kpt_fullbz(3,nkpt_fullbz)
     191                 :             : 
     192                 :             : !Local variables-------------------------------
     193                 :             : !scalars
     194                 :             :  integer :: ialltetra,ikpt2,ikpt_full,isummit,itetra,jalltetra,jsummit
     195                 :             :  integer :: ii,jj,ikibz,nkpt_ibz, my_rank, nprocs
     196                 :             :  integer :: symrankkpt,mtetra,itmp,ntetra_irred
     197                 :             :  real(dp) :: shift1,shift2,shift3, rcvol,hashfactor
     198                 :             :  !real :: cpu_start, cpu_stop
     199                 :           4 :  type(krank_t) :: krank
     200                 :             : !arrays
     201                 :             :  integer :: ind_ibz(4), tetra_shifts(3,4,6)  ! 3 dimensions, 4 summits, and 6 tetrahedra / kpoint box
     202                 :             :  real(dp)  :: k1(3),k2(3),k3(3)
     203                 :           4 :  integer,allocatable :: tetra_full_(:,:,:)
     204                 :           4 :  integer,allocatable :: tetra_mult_(:)
     205                 :           4 :  integer,allocatable :: tetra_wrap_(:,:,:)
     206                 :           4 :  integer, allocatable :: reforder(:)
     207                 :           4 :  integer, allocatable :: irred_itetra(:)
     208         [ -  + ]:           4 :  real(dp), allocatable :: tetra_hash(:)
     209                 :             : 
     210                 :             : ! *********************************************************************
     211                 :             : 
     212                 :             :  !call cpu_time(cpu_start)
     213                 :             : 
     214                 :           4 :  my_rank = 0; nprocs = 1
     215                 :             : #ifdef HAVE_LIBTETRA_ABINIT
     216                 :           4 :  my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
     217                 :             : #endif
     218                 :             : 
     219                 :           4 :  ierr = 0
     220                 :           4 :  errorstring = ""
     221                 :             : !jmb
     222                 :           4 :  shift1 = zero
     223                 :           4 :  shift2 = zero
     224                 :           4 :  shift3 = zero
     225                 :             : 
     226   [ +  +  +  + ]:          52 :  tetra%klatt = klatt
     227                 :             : 
     228                 :           4 :  mtetra = 6 * nkpt_fullbz
     229   [ -  +  +  -  :          12 :  TETRA_ALLOCATE(tetra_full_, (4,2,mtetra))
          +  -  +  -  -  
                +  -  + ]
     230   [ -  +  +  -  :          12 :  TETRA_ALLOCATE(tetra_mult_, (mtetra))
          +  -  +  -  -  
                +  -  + ]
     231   [ -  +  +  -  :          12 :  TETRA_ALLOCATE(tetra_wrap_, (3,4,mtetra))
          +  -  +  -  -  
                +  -  + ]
     232                 :             : 
     233         [ +  + ]:        5188 :  tetra_mult_ = 1
     234   [ +  +  +  +  :       57028 :  tetra_full_ = 0
                   +  + ]
     235   [ +  +  +  +  :       88132 :  tetra_wrap_ = 0
                   +  + ]
     236                 :             : 
     237                 :             : ! tetra_shifts(:,1,1) = (/0,0,0/)
     238                 :             : ! tetra_shifts(:,2,1) = (/0,1,0/)
     239                 :             : ! tetra_shifts(:,3,1) = (/0,1,1/)
     240                 :             : ! tetra_shifts(:,4,1) = (/1,1,0/)
     241                 :             : ! tetra_shifts(:,1,2) = (/0,0,0/)
     242                 :             : ! tetra_shifts(:,2,2) = (/0,1,1/)
     243                 :             : ! tetra_shifts(:,3,2) = (/1,1,0/)
     244                 :             : ! tetra_shifts(:,4,2) = (/1,1,1/)
     245                 :             : ! tetra_shifts(:,1,3) = (/0,0,0/)
     246                 :             : ! tetra_shifts(:,2,3) = (/1,0,0/)
     247                 :             : ! tetra_shifts(:,3,3) = (/1,1,0/)
     248                 :             : ! tetra_shifts(:,4,3) = (/1,1,1/)
     249                 :             : ! tetra_shifts(:,1,4) = (/0,0,0/)
     250                 :             : ! tetra_shifts(:,2,4) = (/0,0,1/)
     251                 :             : ! tetra_shifts(:,3,4) = (/1,0,0/)
     252                 :             : ! tetra_shifts(:,4,4) = (/1,1,1/)
     253                 :             : ! tetra_shifts(:,1,5) = (/0,0,1/)
     254                 :             : ! tetra_shifts(:,2,5) = (/1,0,0/)
     255                 :             : ! tetra_shifts(:,3,5) = (/1,0,1/)
     256                 :             : ! tetra_shifts(:,4,5) = (/1,1,1/)
     257                 :             : ! tetra_shifts(:,1,6) = (/0,0,0/)
     258                 :             : ! tetra_shifts(:,2,6) = (/0,0,1/)
     259                 :             : ! tetra_shifts(:,3,6) = (/0,1,1/)
     260                 :             : ! tetra_shifts(:,4,6) = (/1,1,1/)
     261                 :             : 
     262                 :             :  ! bxu, the following division scheme is according to Bloechl's paper
     263         [ +  + ]:          16 :  tetra_shifts(:,1,1) = (/0,0,0/)
     264         [ +  + ]:          16 :  tetra_shifts(:,2,1) = (/1,0,0/)
     265         [ +  + ]:          16 :  tetra_shifts(:,3,1) = (/0,1,0/)
     266         [ +  + ]:          16 :  tetra_shifts(:,4,1) = (/1,0,1/)
     267         [ +  + ]:          16 :  tetra_shifts(:,1,2) = (/1,0,0/)
     268         [ +  + ]:          16 :  tetra_shifts(:,2,2) = (/1,1,0/)
     269         [ +  + ]:          16 :  tetra_shifts(:,3,2) = (/0,1,0/)
     270         [ +  + ]:          16 :  tetra_shifts(:,4,2) = (/1,0,1/)
     271         [ +  + ]:          16 :  tetra_shifts(:,1,3) = (/0,1,0/)
     272         [ +  + ]:          16 :  tetra_shifts(:,2,3) = (/1,1,0/)
     273         [ +  + ]:          16 :  tetra_shifts(:,3,3) = (/1,0,1/)
     274         [ +  + ]:          16 :  tetra_shifts(:,4,3) = (/1,1,1/)
     275         [ +  + ]:          16 :  tetra_shifts(:,1,4) = (/0,0,0/)
     276         [ +  + ]:          16 :  tetra_shifts(:,2,4) = (/0,1,0/)
     277         [ +  + ]:          16 :  tetra_shifts(:,3,4) = (/0,0,1/)
     278         [ +  + ]:          16 :  tetra_shifts(:,4,4) = (/1,0,1/)
     279         [ +  + ]:          16 :  tetra_shifts(:,1,5) = (/0,0,1/)
     280         [ +  + ]:          16 :  tetra_shifts(:,2,5) = (/1,0,1/)
     281         [ +  + ]:          16 :  tetra_shifts(:,3,5) = (/0,1,0/)
     282         [ +  + ]:          16 :  tetra_shifts(:,4,5) = (/0,1,1/)
     283         [ +  + ]:          16 :  tetra_shifts(:,1,6) = (/0,1,0/)
     284         [ +  + ]:          16 :  tetra_shifts(:,2,6) = (/1,0,1/)
     285         [ +  + ]:          16 :  tetra_shifts(:,3,6) = (/0,1,1/)
     286         [ +  + ]:          16 :  tetra_shifts(:,4,6) = (/1,1,1/)
     287                 :             : 
     288                 :             :  ! Make full k-point rank arrays
     289                 :             :  ! TODO: Lot of memory allocated here if dense mesh e.g ~ 300 ** 3
     290                 :           4 :  call krank%init(nkpt_fullbz, kpt_fullbz)
     291                 :             : 
     292                 :           4 :  ialltetra = 1
     293         [ +  + ]:         868 :  do ikpt_full=1,nkpt_fullbz
     294         [ +  + ]:        6052 :    do itetra=1,6
     295                 :             :      !ialltetra = itetra + (ikpt_full -1) * 6
     296                 :             :      !if (mod(ialltetra, nprocs) /= my_rank) cycle ! MPI parallelism.
     297         [ +  + ]:       25920 :      do isummit=1,4
     298                 :             :        k1(:) = kpt_fullbz(:,ikpt_full) &
     299                 :             :         + tetra_shifts(1,isummit,itetra)*klatt(:,1) &
     300                 :             :         + tetra_shifts(2,isummit,itetra)*klatt(:,2) &
     301         [ +  + ]:       82944 :         + tetra_shifts(3,isummit,itetra)*klatt(:,3)
     302                 :             : 
     303                 :             :        ! Find full kpoint which is summit isummit of tetrahedron itetra around full kpt ikpt_full !
     304                 :       20736 :        symrankkpt =  krank%get_rank(k1)
     305                 :       20736 :        ikpt2 = krank%invrank(symrankkpt)
     306         [ -  + ]:       20736 :        if (ikpt2 < 1) then
     307                 :           0 :          errorstring = 'Error in ranking k-points - exiting with un-initialized tetrahedra.'
     308                 :           0 :          ierr = 2
     309                 :           0 :          call krank%free()
     310   [ #  #  #  # ]:           0 :          TETRA_ALLOCATE(tetra%tetra_full, (4,2,1))
     311   [ #  #  #  # ]:           0 :          TETRA_ALLOCATE(tetra%tetra_mult, (1))
     312   [ #  #  #  # ]:           0 :          TETRA_ALLOCATE(tetra%tetra_wrap, (3,4,1))
     313         [ #  # ]:           0 :          TETRA_DEALLOCATE(tetra_full_)
     314         [ #  # ]:           0 :          TETRA_DEALLOCATE(tetra_mult_)
     315         [ #  # ]:           0 :          TETRA_DEALLOCATE(tetra_wrap_)
     316                 :           0 :          return
     317                 :             :        end if
     318                 :             : 
     319                 :             :        ! Store irreducible kpoint equivalent to kpt_fullbz(:,ikpt2)
     320                 :       20736 :        tetra_full_(isummit,1,ialltetra) = indkpt(ikpt2)
     321                 :       20736 :        tetra_full_(isummit,2,ialltetra) = ikpt2
     322                 :       20736 :        shift1 = k1(1)-kpt_fullbz(1,ikpt2)
     323                 :       20736 :        shift2 = k1(2)-kpt_fullbz(2,ikpt2)
     324                 :       20736 :        shift3 = k1(3)-kpt_fullbz(3,ikpt2)
     325         [ +  + ]:       20736 :        if (shift1>0.5d0) then
     326                 :        1728 :          tetra_wrap_(1,isummit,ialltetra) = 1
     327         [ -  + ]:       19008 :        else if (shift1<-0.5d0) then
     328                 :           0 :          tetra_wrap_(1,isummit,ialltetra) = -1
     329                 :             :        end if
     330         [ +  + ]:       20736 :        if (shift2>0.5d0) then
     331                 :        1728 :          tetra_wrap_(2,isummit,ialltetra) = 1
     332         [ -  + ]:       19008 :        else if (shift2<-0.5d0) then
     333                 :           0 :          tetra_wrap_(2,isummit,ialltetra) = -1
     334                 :             :        end if
     335         [ +  + ]:       20736 :        if (shift3>0.5d0) then
     336                 :        1728 :          tetra_wrap_(3,isummit,ialltetra) = 1
     337         [ +  - ]:       19008 :        else if (shift3<-0.5d0) then
     338                 :           0 :          tetra_wrap_(3,isummit,ialltetra) = -1
     339                 :             :        end if
     340                 :             : 
     341                 :             :        ! sort itetra summits
     342                 :             :        ! TODO: replace with sort_int
     343         [ +  + ]:       57024 :        do jsummit=isummit,2,-1
     344         [ +  + ]:       51840 :          if ( tetra_full_(jsummit,1,ialltetra)  <  tetra_full_(jsummit-1,1,ialltetra) ) then
     345                 :        6912 :            itmp = tetra_full_(jsummit,1,ialltetra)
     346                 :        6912 :            tetra_full_(jsummit,1,ialltetra) = tetra_full_(jsummit-1,1,ialltetra)
     347                 :        6912 :            tetra_full_(jsummit-1,1,ialltetra) = itmp
     348                 :        6912 :            itmp = tetra_full_(jsummit,2,ialltetra)
     349                 :        6912 :            tetra_full_(jsummit,2,ialltetra) = tetra_full_(jsummit-1,2,ialltetra)
     350                 :        6912 :            tetra_full_(jsummit-1,2,ialltetra) = itmp
     351                 :             :            ! keep fullbz_kpt tetrahedra points in same order
     352                 :        6912 :            itmp = tetra_wrap_(1,jsummit,ialltetra)
     353                 :        6912 :            tetra_wrap_(1,jsummit,ialltetra) = tetra_wrap_(1,jsummit-1,ialltetra)
     354                 :        6912 :            tetra_wrap_(1,jsummit-1,ialltetra) = itmp
     355                 :        6912 :            itmp = tetra_wrap_(2,jsummit,ialltetra)
     356                 :        6912 :            tetra_wrap_(2,jsummit,ialltetra) = tetra_wrap_(2,jsummit-1,ialltetra)
     357                 :        6912 :            tetra_wrap_(2,jsummit-1,ialltetra) = itmp
     358                 :        6912 :            itmp = tetra_wrap_(1,jsummit,ialltetra)
     359                 :        6912 :            tetra_wrap_(3,jsummit,ialltetra) = tetra_wrap_(3,jsummit-1,ialltetra)
     360                 :        6912 :            tetra_wrap_(3,jsummit-1,ialltetra) = itmp
     361                 :             :          end if
     362                 :             :        end do ! jsummit
     363                 :             : 
     364                 :             :      end do ! isummit
     365                 :             : 
     366         [ -  + ]:        5184 :      if (ialltetra > mtetra) then
     367                 :             :        write (errorstring, '(3a,i0,a,i0)' ) &
     368                 :           0 :         'init_tetra: BUG - ',&
     369                 :           0 :         ' ialltetra > mtetra ',&
     370                 :           0 :         ' ialltetra=  ',ialltetra,', mtetra= ',mtetra
     371                 :           0 :        ierr = 1
     372                 :           0 :        return
     373                 :             :      end if
     374                 :        6048 :      ialltetra = ialltetra+1
     375                 :             :    end do ! itetra
     376                 :             :  end do ! ikpt_full
     377                 :             : 
     378                 :             :  !call cpu_time(cpu_stop)
     379                 :             :  !write(*,*)"tetra_init ikpt_loop:", cpu_stop - cpu_start
     380                 :             :  !cpu_start = cpu_stop
     381                 :             : 
     382                 :           4 :  call krank%free()
     383                 :             : 
     384                 :             :  rcvol = abs (gprimd(1,1)*(gprimd(2,2)*gprimd(3,3)-gprimd(3,2)*gprimd(2,3)) &
     385                 :             : & -gprimd(2,1)*(gprimd(1,2)*gprimd(3,3)-gprimd(3,2)*gprimd(1,3)) &
     386                 :           4 : & +gprimd(3,1)*(gprimd(1,2)*gprimd(2,3)-gprimd(2,2)*gprimd(1,3)))
     387                 :             : 
     388                 :             :  ! Volume of all tetrahedra should be the same as that of tetra 1
     389                 :             :  ! this is the volume of 1 tetrahedron, should be coherent with notation in Lehmann & Taut
     390         [ +  + ]:          16 :  k1(:) = gprimd(:,1)*klatt(1,1) +  gprimd(:,2)*klatt(2,1) +  gprimd(:,3)*klatt(3,1)
     391         [ +  + ]:          16 :  k2(:) = gprimd(:,1)*klatt(1,2) +  gprimd(:,2)*klatt(2,2) +  gprimd(:,3)*klatt(3,2)
     392         [ +  + ]:          16 :  k3(:) = gprimd(:,1)*klatt(1,3) +  gprimd(:,2)*klatt(2,3) +  gprimd(:,3)*klatt(3,3)
     393                 :             :  tetra%vv  = abs (k1(1)*(k2(2)*k3(3)-k2(3)*k3(2)) &
     394                 :             : & -k1(2)*(k2(1)*k3(3)-k2(3)*k3(1)) &
     395                 :           4 : & +k1(3)*(k2(1)*k3(2)-k2(2)*k3(1))) / 6.d0 / rcvol
     396                 :             : 
     397                 :             :  ! eliminate equivalent tetrahedra by symmetry and account for them in multiplicity tetra_mult
     398                 :           4 :  tetra%ntetra = mtetra
     399                 :             : 
     400                 :             :  ! FIXME: could we replace this with a ranking algorithm to avoid the O(tetra%ntetra^2) step? For example:
     401                 :             :  ! get tetrahedron rank - problem too many combinations in principle = nkpt_irred^4 - only a few used in practice
     402                 :             :  ! sort ranks and keep indices
     403                 :             : 
     404                 :             :  ! make hash table = tetra_full_(1)*nkptirred**3+tetra_full_(2)*nkptirred**2+tetra_full_(3)*nkptirred**1+tetra_full_(4)
     405                 :             : 
     406                 :           4 :  hashfactor = 100.d0 ! *acos(-1.d0) ! 100 pi should be far from an integer...
     407   [ -  +  +  -  :          12 :  TETRA_ALLOCATE(tetra_hash, (tetra%ntetra))
          +  -  +  -  -  
                +  -  + ]
     408   [ -  +  +  -  :          12 :  TETRA_ALLOCATE(reforder, (tetra%ntetra))
          +  -  +  -  -  
                +  -  + ]
     409                 :             : 
     410                 :             :  !MG: In principle the order of the indices should not matter.
     411         [ +  + ]:        5188 :  do ialltetra=1, tetra%ntetra
     412                 :             :    tetra_hash(ialltetra) = tetra_full_(1,1,ialltetra)*hashfactor**3+&
     413                 :             : &      tetra_full_(2,1,ialltetra)*hashfactor**2+&
     414                 :             : &      tetra_full_(3,1,ialltetra)*hashfactor**1+&
     415                 :        5184 : &      tetra_full_(4,1,ialltetra)
     416                 :        5188 :    reforder(ialltetra) = ialltetra
     417                 :             :  end do
     418                 :             : 
     419                 :           4 :  call sort_tetra(tetra%ntetra, tetra_hash, reforder, tol14)
     420                 :             :  ! Most of the wall-time is spent in the  preamble of this routine (up to this point).
     421                 :             :  ! sort_tetra is not easy to parallelize...
     422                 :             : 
     423                 :             :  ! determine number of tetra after reduction
     424   [ -  +  +  -  :          12 :  TETRA_ALLOCATE(irred_itetra, (tetra%ntetra))
          +  -  +  -  -  
                +  -  + ]
     425                 :           4 :  jalltetra = 1
     426                 :           4 :  irred_itetra(1) = 1
     427         [ +  + ]:        5184 :  do ialltetra=2, tetra%ntetra
     428         [ +  - ]:        5180 :    if (abs(tetra_hash(ialltetra)-tetra_hash(ialltetra-1)) > tol14) then
     429                 :             :      ! found a new series
     430                 :        5180 :      jalltetra = jalltetra + 1
     431                 :             :    end if
     432                 :        5184 :    irred_itetra(ialltetra) = jalltetra
     433                 :             :  end do
     434                 :             : 
     435                 :             :  ! reset number of tetra
     436                 :           4 :  ntetra_irred = jalltetra
     437                 :             : 
     438                 :             :  ! allocate definitive tetra arrays and transfer to new arrays
     439   [ -  +  +  -  :          12 :  TETRA_ALLOCATE(tetra%tetra_full, (4,2,ntetra_irred))
          +  -  -  +  -  
                +  -  + ]
     440   [ -  +  +  -  :          12 :  TETRA_ALLOCATE(tetra%tetra_mult, (ntetra_irred))
          +  -  -  +  -  
                +  -  + ]
     441   [ -  +  +  -  :          12 :  TETRA_ALLOCATE(tetra%tetra_wrap, (3,4,ntetra_irred))
          +  -  -  +  -  
                +  -  + ]
     442                 :             : 
     443                 :             :  ! eliminate equal rank tetrahedra and accumulate multiplicity into first one
     444   [ +  +  +  +  :       57028 :  tetra%tetra_full = 0
                   +  + ]
     445         [ +  + ]:        5188 :  tetra%tetra_mult = 0
     446   [ +  +  +  +  :       88132 :  tetra%tetra_wrap = 0
                   +  + ]
     447                 :           4 :  jalltetra = 1
     448   [ +  +  +  + ]:          44 :  tetra%tetra_full(:,:,1) = tetra_full_(:,:,reforder(1))
     449                 :           4 :  tetra%tetra_mult(1) = 1
     450   [ +  +  +  + ]:          68 :  tetra%tetra_wrap(:,:,1) = tetra_wrap_(:,:,reforder(1))
     451         [ +  + ]:        5184 :  do ialltetra=2, tetra%ntetra
     452                 :             :    ! TODO: check if tolerance is adapted
     453         [ +  - ]:        5184 :    if (abs(tetra_hash(ialltetra)-tetra_hash(ialltetra-1)) > tol14) then
     454                 :             :      ! found a new series
     455                 :        5180 :      jalltetra = jalltetra + 1
     456   [ +  +  +  + ]:       56980 :      tetra%tetra_full(:,:,jalltetra) = tetra_full_(:,:,reforder(ialltetra))
     457   [ +  +  +  + ]:       88060 :      tetra%tetra_wrap(:,:,jalltetra) = tetra_wrap_(:,:,reforder(ialltetra))
     458                 :        5180 :      tetra%tetra_mult(jalltetra) = 1
     459                 :             :    else
     460                 :             :      ! TODO: add real check that the tetra are equivalent...
     461                 :             :      ! otherwise increment jalltetra here as well, generate new series?
     462                 :           0 :      tetra%tetra_mult(jalltetra) = tetra%tetra_mult(jalltetra) + tetra_mult_(reforder(ialltetra))
     463                 :             :      !tetra_mult_(reforder(ialltetra)) = 0
     464                 :             :    end if
     465                 :             :  end do
     466                 :             : 
     467                 :             :  ! reset of ntetra for final version after checks and debu
     468                 :           4 :  tetra%ntetra = ntetra_irred
     469                 :             : 
     470         [ -  + ]:           4 :  TETRA_DEALLOCATE(tetra_hash)
     471                 :           4 :  TETRA_DEALLOCATE(reforder)
     472                 :           4 :  TETRA_DEALLOCATE(irred_itetra)
     473         [ -  + ]:           4 :  TETRA_DEALLOCATE(tetra_full_)
     474         [ -  + ]:           4 :  TETRA_DEALLOCATE(tetra_mult_)
     475         [ -  + ]:           4 :  TETRA_DEALLOCATE(tetra_wrap_)
     476                 :             : 
     477                 :             :  ! Create mapping between the irreducible k-points
     478                 :             :  ! and all the tetrahedron contributing with some weight
     479         [ +  + ]:         868 :  nkpt_ibz = maxval(indkpt)
     480                 :             : 
     481                 :             :  ! 1. First we count what is the maximum number of distinct tetrahedra that each k-point contains
     482   [ -  +  +  -  :          12 :  TETRA_ALLOCATE(tetra%ibz_tetra_count,(nkpt_ibz))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     483         [ +  + ]:         868 :  tetra%ibz_tetra_count(:) = 0
     484                 :             : 
     485                 :             :  ! Count max tetra contributing
     486         [ +  + ]:        5188 :  do ii=1,tetra%ntetra
     487                 :             :    ! Here we need the original ordering to reference the correct irred kpoints
     488         [ +  + ]:       25920 :    ind_ibz(:) = tetra%tetra_full(:,1,ii)
     489                 :             :    ! count max tetra contributing
     490         [ +  + ]:       25924 :    do jj=1,4
     491                 :       20736 :      ikibz = ind_ibz(jj)
     492         [ -  + ]:       20736 :      if (ikibz > nkpt_ibz) cycle
     493                 :       25920 :      tetra%ibz_tetra_count(ikibz) = tetra%ibz_tetra_count(ikibz) + 1
     494                 :             :    end do
     495                 :             :  end do
     496                 :             : 
     497                 :             :  ! 2. Then we build mapping of ikbz to tetra
     498   [ -  +  +  -  :         880 :  TETRA_ALLOCATE(tetra%ibz_tetra_mapping,(nkpt_ibz,maxval(tetra%ibz_tetra_count)))
          +  +  -  +  +  
          -  +  -  +  -  
          -  +  -  +  -  
                      + ]
     499         [ +  + ]:         868 :  tetra%ibz_tetra_count(:) = 0
     500         [ +  + ]:        5188 :  do ii=1,tetra%ntetra
     501                 :             :    ! Here we need the original ordering to reference the correct irred kpoints
     502         [ +  + ]:       25920 :    ind_ibz(:) = tetra%tetra_full(:,1,ii)
     503                 :             :    ! Use the counter to move pointer and then fill index
     504         [ +  + ]:       25924 :    do jj=1,4
     505                 :       20736 :      ikibz = ind_ibz(jj)
     506         [ -  + ]:       20736 :      if (ikibz > nkpt_ibz) cycle
     507                 :             :      ! avoid putting the same index twice
     508         [ +  + ]:       20736 :      if (tetra%ibz_tetra_count(ikibz) > 0) then
     509         [ -  + ]:       19872 :        if (tetra%ibz_tetra_mapping(ikibz,tetra%ibz_tetra_count(ikibz)) == ii) cycle
     510                 :             :      end if
     511                 :       20736 :      tetra%ibz_tetra_count(ikibz) = tetra%ibz_tetra_count(ikibz) + 1
     512                 :       25920 :      tetra%ibz_tetra_mapping(ikibz,tetra%ibz_tetra_count(ikibz)) = ii
     513                 :             :    end do
     514                 :             :  end do
     515                 :             : 
     516                 :             :  !call cpu_time(cpu_stop)
     517                 :             :  !write(*,*)"tetra_init 2nd part:", cpu_stop - cpu_start
     518                 :             :  !cpu_start = cpu_stop
     519                 :             : 
     520   [ -  +  -  +  :           4 : end subroutine init_tetra
          -  +  -  +  -  
                +  -  + ]
     521                 :             : !!***
     522                 :             : 
     523                 :             : !----------------------------------------------------------------------
     524                 :             : 
     525                 :             : !!****f* m_tetrahedron/tetra_write
     526                 :             : !! NAME
     527                 :             : !! tetra_write
     528                 :             : !!
     529                 :             : !! FUNCTION
     530                 :             : !!  Write text file with tetra info.
     531                 :             : !!
     532                 :             : !! INPUTS
     533                 :             : !!  tetra<t_tetrahedron>=tetrahedron geometry object
     534                 :             : !!  nkibz=Number of k-points in the IBZ used to generate tetra
     535                 :             : !!  kibz(3,nkibz)=Reduced coordinates of the IBZ
     536                 :             : !!  path=Name of output file
     537                 :             : !!
     538                 :             : !! OUTPUT
     539                 :             : !!  Output is written to file.
     540                 :             : !!
     541                 :             : !! SOURCE
     542                 :             : 
     543                 :           0 : subroutine tetra_write(tetra, nkibz, kibz, path)
     544                 :             : 
     545                 :             : !Arguments ------------------------------------
     546                 :             : !scalars
     547                 :             :  integer,intent(in) :: nkibz
     548                 :             :  character(len=*),intent(in) :: path
     549                 :             :  type(t_tetrahedron),intent(in) :: tetra
     550                 :             : !arrays
     551                 :             :  real(dp),intent(in) :: kibz(3,nkibz)
     552                 :             : 
     553                 :             : !Local variables-------------------------------
     554                 :             :  integer,parameter :: version=1
     555                 :             :  integer :: ik,it,unt
     556                 :             : #ifdef HAVE_LIBTETRA_ABINIT
     557                 :             :  character(len=500) :: msg
     558                 :             : #endif
     559                 :             : 
     560                 :             : ! *********************************************************************
     561                 :             : 
     562                 :             : #ifdef HAVE_LIBTETRA_ABINIT
     563         [ #  # ]:           0 :  if (open_file(file=trim(path),iomsg=msg,newunit=unt,form="formatted",status="unknown",action="write")/=0) then
     564                 :           0 :    TETRA_ERROR(msg)
     565                 :             :  end if
     566                 :             : #else
     567                 :             :  open(file=trim(path),newunit=unt,form="formatted",status="unknown",action="write")
     568                 :             : #endif
     569                 :             : 
     570                 :           0 :  write(unt,*)version, " # version number"
     571                 :             : 
     572                 :             :  ! Write IBZ
     573                 :           0 :  write(unt,*)nkibz, " # number of k-points in the IBZ"
     574                 :           0 :  write(unt,"(a)")"<irreducible_zone>"
     575         [ #  # ]:           0 :  do ik=1,nkibz
     576                 :           0 :    write(unt,"(3es22.12)") kibz(:,ik)
     577                 :             :  end do
     578                 :           0 :  write(unt,"(a)")"</irreducible_zone>"
     579                 :             : 
     580                 :             :  ! Write tetra info
     581                 :           0 :  write(unt,"(i0,a)")tetra%ntetra, " # number of tetrahedra"
     582                 :           0 :  write(unt,"(es22.12,a)")tetra%vv, " # tetrahedron volume"
     583                 :             : 
     584                 :           0 :  write(unt,"(a)")"<tetra_full>"
     585         [ #  # ]:           0 :  do it=1,tetra%ntetra
     586                 :           0 :    write(unt,"(8(i0,1x))")tetra%tetra_full(:,:,it)
     587                 :             :  end do
     588                 :           0 :  write(unt,"(a)")"</tetra_full>"
     589                 :             : 
     590                 :           0 :  write(unt,"(a)")"<tetra_mult>"
     591         [ #  # ]:           0 :  do it=1,tetra%ntetra
     592                 :           0 :    write(unt,"(i0)")tetra%tetra_mult(it)
     593                 :             :  end do
     594                 :           0 :  write(unt,"(a)")"</tetra_mult>"
     595                 :             : 
     596                 :           0 :  write(unt,"(a)")"<tetra_wrap>"
     597         [ #  # ]:           0 :  do it=1,tetra%ntetra
     598                 :           0 :    write(unt,"(12(i0,1x))")tetra%tetra_wrap(:,:,it)
     599                 :             :  end do
     600                 :           0 :  write(unt,"(a)")"</tetra_wrap>"
     601                 :             : 
     602                 :           0 :  close(unt)
     603                 :             : 
     604                 :           0 : end subroutine tetra_write
     605                 :             : !!***
     606                 :             : 
     607                 :             : !----------------------------------------------------------------------
     608                 :             : 
     609                 :             : !!****f* m_tetrahedron/get_tetra_weight
     610                 :             : !! NAME
     611                 :             : !! get_tetra_weight
     612                 :             : !!
     613                 :             : !! FUNCTION
     614                 :             : !! calculate integration weights and their derivatives from Blochl et al PRB 49 16223 [[cite:Bloechl1994a]]
     615                 :             : !!
     616                 :             : !! INPUTS
     617                 :             : !! eigen_in(nkpt)=eigenenergies for each k point
     618                 :             : !! enemin=minimal energy for DOS
     619                 :             : !! enemax=maximal energy for DOS
     620                 :             : !! max_occ=maximal occupation number (2 for nsppol=1, 1 for nsppol=2)
     621                 :             : !! nene=number of energies for DOS
     622                 :             : !! nkpt=number of irreducible kpoints
     623                 :             : !! tetra<t_tetrahedron>
     624                 :             : !!   %ntetra=number of tetrahedra
     625                 :             : !!   %tetra_full(4,2,ntetra)=for each irred tetrahedron, the list of k point vertices
     626                 :             : !!     1 -> irred kpoint   2 -> fullkpt
     627                 :             : !!   %tetra_mult(ntetra)=for each irred tetrahedron, its multiplicity
     628                 :             : !!   %vv = ratio of volume of one tetrahedron in reciprocal space to full BZ volume
     629                 :             : !! bcorr=1 to include Blochl correction else 0.
     630                 :             : !! comm=MPI communicator
     631                 :             : !!
     632                 :             : !! OUTPUT
     633                 :             : !!  tweight(nkpt,nene) = integration weights for each irred kpoint from all adjacent tetrahedra
     634                 :             : !!  dtweightde(nkpt,nene) = derivative of tweight wrt energy
     635                 :             : !!
     636                 :             : !! SOURCE
     637                 :             : 
     638                 :             : ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     639                 :             : ! THIS FUNCTION IS DEPRECATED, USE tetra_blochl_weights
     640                 :             : ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     641                 :          18 : subroutine get_tetra_weight(eigen_in,enemin,enemax,max_occ,nene,nkpt,tetra,&
     642                 :          18 :   bcorr,tweight,dtweightde,comm)
     643                 :             : 
     644                 :             : !Arguments ------------------------------------
     645                 :             : !scalars
     646                 :             :  integer,intent(in) :: nene,nkpt,bcorr,comm
     647                 :             :  type(t_tetrahedron), intent(in) :: tetra
     648                 :             :  real(dp) ,intent(in) :: enemax,enemin,max_occ
     649                 :             : !arrays
     650                 :             :  real(dp) ,intent(in) :: eigen_in(nkpt)
     651                 :             :  real(dp) ,intent(out) :: dtweightde(nkpt,nene),tweight(nkpt,nene)
     652                 :             : 
     653                 :             : !Local variables-------------------------------
     654                 :          18 :  real(dp), allocatable :: dtweightde_ek(:, :), tweight_ek(:, :)
     655                 :             : 
     656                 :             : ! *********************************************************************
     657                 :             : 
     658   [ -  +  +  -  :          72 :  TETRA_ALLOCATE(dtweightde_ek, (nene, nkpt))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     659   [ -  +  +  -  :          54 :  TETRA_ALLOCATE(tweight_ek, (nene, nkpt))
          -  +  +  -  -  
                +  -  + ]
     660                 :             : 
     661                 :          18 :  call tetra_blochl_weights(tetra,eigen_in,enemin,enemax,max_occ,nene,nkpt,bcorr,tweight_ek,dtweightde_ek,comm)
     662                 :             : 
     663                 :             :  ! transpose: otherwise the data access is crap and the code slows by an order of magnitude
     664   [ +  +  +  + ]:      782520 :  tweight    = transpose(tweight_ek)
     665   [ +  +  +  + ]:      782520 :  dtweightde = transpose(dtweightde_ek)
     666                 :             : 
     667         [ -  + ]:          18 :  TETRA_DEALLOCATE(dtweightde_ek)
     668         [ -  + ]:          18 :  TETRA_DEALLOCATE(tweight_ek)
     669                 :             : 
     670                 :          18 : end subroutine get_tetra_weight
     671                 :             : !!***
     672                 :             : 
     673                 :             : !----------------------------------------------------------------------
     674                 :             : 
     675                 :             : !!****f* m_tetrahedron/tetra_blochl_weights
     676                 :             : !! NAME
     677                 :             : !! tetra_blochl_weights
     678                 :             : !!
     679                 :             : !! FUNCTION
     680                 :             : !! calculate integration weights and their derivatives from Blochl et al PRB 49 16223 [[cite:Bloechl1994a]]
     681                 :             : !! Same API as get_tetra_weight but output weights here have shape (nene, nkpt)
     682                 :             : !!
     683                 :             : !! SOURCE
     684                 :             : 
     685                 :          18 : subroutine tetra_blochl_weights(tetra,eigen_in,enemin,enemax,max_occ,nene,nkpt,&
     686                 :          18 :   bcorr,tweight_t,dtweightde_t,comm)
     687                 :             : 
     688                 :             : !Arguments ------------------------------------
     689                 :             : !scalars
     690                 :             :  integer,intent(in) :: nene,nkpt,bcorr,comm
     691                 :             :  type(t_tetrahedron), intent(in) :: tetra
     692                 :             :  real(dp) ,intent(in) :: enemax,enemin,max_occ
     693                 :             : !arrays
     694                 :             :  real(dp) ,intent(in) :: eigen_in(nkpt)
     695                 :             :  real(dp) ,intent(out) :: dtweightde_t(nene,nkpt),tweight_t(nene,nkpt)
     696                 :             : 
     697                 :             : !Local variables-------------------------------
     698                 :             : !scalars
     699                 :             :  integer :: itetra,nprocs,my_start,my_stop,ierr,ii
     700                 :             : !arrays
     701                 :             :  integer :: ind_ibz(4)
     702                 :             :  real(dp) :: eigen_1tetra(4)
     703                 :          18 :  real(dp), allocatable :: tweight_tmp(:,:),dtweightde_tmp(:,:),buffer(:,:)
     704                 :             : 
     705                 :             : ! *********************************************************************
     706                 :             : 
     707   [ -  +  +  -  :          54 :  TETRA_ALLOCATE(tweight_tmp, (nene, 4))
          +  -  +  -  -  
                +  -  + ]
     708   [ -  +  +  -  :          36 :  TETRA_ALLOCATE(dtweightde_tmp, (nene, 4))
             -  +  +  - ]
     709   [ +  +  +  +  :     1565604 :  tweight_t = zero; dtweightde_t = zero
             +  +  +  + ]
     710                 :             : 
     711                 :          18 :  call split_work(tetra%ntetra, comm, nprocs, my_start, my_stop, ierr)
     712         [ -  + ]:          18 :  if (ierr /= 0) TETRA_ERROR("Error in MPI layer")
     713                 :             : 
     714                 :             :  ! for each tetrahedron
     715         [ +  + ]:       23346 :  do itetra=my_start,my_stop
     716   [ +  +  +  + ]:    18810144 :    tweight_tmp = zero
     717   [ +  +  +  + ]:    18810144 :    dtweightde_tmp = zero
     718                 :             : 
     719                 :             :    ! Here we need the original ordering to reference the correct irred kpoints
     720         [ +  + ]:      116640 :    ind_ibz(:) = tetra%tetra_full(:,1,itetra)
     721                 :             : 
     722                 :             :    ! Sort energies before calling get_onetetra_
     723         [ +  + ]:      116640 :    eigen_1tetra(:) = eigen_in(ind_ibz(:))
     724                 :       23328 :    call sort_tetra(4, eigen_1tetra, ind_ibz, tol14)
     725                 :             : 
     726                 :       23328 :    call get_onetetra_(tetra,itetra,eigen_1tetra,enemin,enemax,max_occ,nene,bcorr,tweight_tmp,dtweightde_tmp)
     727                 :             : 
     728                 :             :    ! NOTE: the following blas calls are not working systematically, or do not give speed ups, strange...
     729                 :             :    !if (nene > 100) then
     730                 :             :    !  do ii=1,4
     731                 :             :    !    call daxpy (nene, 1.d0, tweight_tmp(:,ii), 1, tweight_t(:,ind_ibz(ii)), 1)
     732                 :             :    !  end do
     733                 :             :    !  do ii=1,4
     734                 :             :    !    call daxpy (nene, 1.d0, dtweightde_tmp(:,ii), 1, dtweightde_t(:,ind_ibz(ii)), 1)
     735                 :             :    !  end do
     736                 :             :    !else
     737         [ +  + ]:      116640 :    do ii=1,4
     738         [ +  + ]:    18810144 :      tweight_t(:,ind_ibz(ii)) = tweight_t(:,ind_ibz(ii)) + tweight_tmp(:,ii)
     739                 :             :    end do
     740         [ +  + ]:      116658 :    do ii=1,4
     741         [ +  + ]:    18810144 :      dtweightde_t(:,ind_ibz(ii)) = dtweightde_t(:,ind_ibz(ii)) + dtweightde_tmp(:,ii)
     742                 :             :    end do
     743                 :             :    !end if
     744                 :             :  end do ! itetra
     745                 :             : 
     746         [ -  + ]:          18 :  TETRA_DEALLOCATE(tweight_tmp)
     747         [ -  + ]:          18 :  TETRA_DEALLOCATE(dtweightde_tmp)
     748                 :             : 
     749         [ -  + ]:          18 :  if (nprocs > 1) then
     750                 :             : #ifdef HAVE_MPI
     751   [ #  #  #  #  :           0 :    TETRA_ALLOCATE(buffer, (nene, nkpt))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     752                 :           0 :    call MPI_ALLREDUCE(tweight_t,buffer,nene*nkpt,MPI_DOUBLE_PRECISION,MPI_SUM,comm,ierr)
     753   [ #  #  #  # ]:           0 :    tweight_t = buffer
     754                 :             : 
     755                 :           0 :    call MPI_ALLREDUCE(dtweightde_t,buffer,nene*nkpt,MPI_DOUBLE_PRECISION,MPI_SUM,comm,ierr)
     756   [ #  #  #  # ]:           0 :    dtweightde_t = buffer
     757         [ #  # ]:           0 :    TETRA_DEALLOCATE(buffer)
     758                 :             : #endif
     759                 :             :  end if
     760                 :             : 
     761                 :          18 : end subroutine tetra_blochl_weights
     762                 :             : !!***
     763                 :             : 
     764                 :             : !----------------------------------------------------------------------
     765                 :             : 
     766                 :             : !!****f* m_tetrahedron/get_dbl_tetra_weight
     767                 :             : !! NAME
     768                 :             : !! get_dbl_tetra_weight
     769                 :             : !!
     770                 :             : !! FUNCTION
     771                 :             : !! calculate integration weights and their derivatives
     772                 :             : !! for double tetrahedron method from Allen Phys Stat Sol B 120 529 (1983) [[cite:Allen1983b]]
     773                 :             : !! the k-points and tetrahedra must be the same for both grids, of course,
     774                 :             : !! but the range of energies is arbitrary
     775                 :             : !!
     776                 :             : !! Omega is called eigen1 here
     777                 :             : !! E is called eigen2 here
     778                 :             : !! indexing goes from 1 to 4 for the tetrahedron corners, in order of increasing eigen1
     779                 :             : !!  in Allen, from 0 to 3...
     780                 :             : !!
     781                 :             : !! INPUTS
     782                 :             : !! eigen1_in(nkpt)=eigenenergies for each k point
     783                 :             : !! eigen2_in(nkpt)=eigenenergies for each k point
     784                 :             : !! enemin1=minimal energy for DOS in energy 1
     785                 :             : !! enemax1=maximal energy for DOS
     786                 :             : !! enemin2=minimal energy for DOS in energy 2
     787                 :             : !! enemax2=maximal energy for DOS
     788                 :             : !! max_occ=maximal occupation number (2 for nsppol=1, 1 for nsppol=2)
     789                 :             : !! nene1=number of energies for DOS in energy 1
     790                 :             : !! nene2=number of energies for DOS in energy 2
     791                 :             : !! nkpt=number of irreducible kpoints
     792                 :             : !! tetra%ntetra=number of tetra
     793                 :             : !! tetra%tetra_full(4,2,ntetra)=for each irred tetrahedron, the list of k point vertices
     794                 :             : !!   1 -> irred kpoint   2 -> fullkpt
     795                 :             : !! tetra%tetra_mult(ntetra)=for each irred tetrahedron, its multiplicity
     796                 :             : !! tetra%vv = ratio of volume of one tetrahedron in reciprocal space to full BZ volume
     797                 :             : !! ierr = error code on exit
     798                 :             : !!
     799                 :             : !! OUTPUT
     800                 :             : !!  tweight(nkpt,nene1,nene2) = integration weights for each irred kpoint from all adjacent tetrahedra
     801                 :             : !!  dtweightde(nkpt,nene1,nene2) = derivative of tweight wrt energy
     802                 :             : !!
     803                 :             : !! SOURCE
     804                 :             : 
     805                 :           0 : subroutine get_dbl_tetra_weight(eigen1_in,eigen2_in,enemin1,enemax1,enemin2,enemax2,&
     806                 :           0 : &    max_occ,nene1,nene2,nkpt,tetra,tweight,dtweightde, ierr)
     807                 :             : 
     808                 :             : !Arguments ------------------------------------
     809                 :             : !scalars
     810                 :             :  integer,intent(in) :: nene1,nene2,nkpt
     811                 :             :  integer,intent(out) :: ierr
     812                 :             :  type(t_tetrahedron), intent(in) :: tetra
     813                 :             :  real(dp),intent(in) :: enemax1,enemin1
     814                 :             :  real(dp),intent(in) :: enemax2,enemin2
     815                 :             :  real(dp),intent(in) :: max_occ
     816                 :             : !arrays
     817                 :             :  real(dp),intent(in) :: eigen1_in(nkpt)
     818                 :             :  real(dp),intent(in) :: eigen2_in(nkpt)
     819                 :             :  real(dp),intent(out) :: dtweightde(nkpt,nene1,nene2),tweight(nkpt,nene1,nene2)
     820                 :             : 
     821                 :             : !Local variables-------------------------------
     822                 :             : !  needed for gaussian replacement of Dirac functions
     823                 :             : !  the three coefficients of the DOS as quadratic form,
     824                 :             : !    in the interval [eig(ikpt-1), eig(ikpt)]
     825                 :             : !    for ikpt = 1 we add a point below eigen(1) which doesnt
     826                 :             : !    contribute to the DOS in any tetrahedron
     827                 :             : !scalars
     828                 :             :  integer :: ieps1,ieps2,itetra
     829                 :             :  integer :: nn1_1,nn1_2,nn1_3,nn1_4
     830                 :             :  integer :: nn2_1,nn2_2,nn2_3
     831                 :             :  integer :: ind_a(3), ind_b(3), ind_c(3)
     832                 :             :  real(dp)  :: deltaene1,eps1
     833                 :             :  real(dp)  :: deltaene2,eps2
     834                 :             : ! real(dp)  :: gau_prefactor,gau_width,gau_width2
     835                 :             :  real(dp)  :: epsilon1(4,4)
     836                 :             :  real(dp)  :: epsilon2(4,4)
     837                 :             :  real(dp)  :: inv_epsilon1(4,4)
     838                 :             :  real(dp)  :: aa(3),bb(3),cc(3)
     839                 :             :  real(dp)  :: delaa(3),delbb(3),delcc(3)
     840                 :             :  real(dp)  :: delaa0,delbb0,delcc0
     841                 :             :  real(dp)  :: inv_delaa(3),inv_delbb(3),inv_delcc(3)
     842                 :             :  real(dp)  :: deleps1, deleps2
     843                 :             :  real(dp)  :: inv_deleps1
     844                 :             :  real(dp)  :: dccde1, dccde1_pre
     845                 :             :  real(dp)  :: volconst,volconst_mult
     846                 :             :  real(dp)  :: ii0, ii1, ii3
     847                 :             : !arrays
     848                 :             :  integer :: ind_k(4)
     849                 :           0 :  real(dp), allocatable :: tweight_tmp(:,:,:)
     850                 :           0 :  real(dp), allocatable :: dtweightde_tmp(:,:,:)
     851                 :             :  real(dp)  :: eigen1_1tetra(4)
     852                 :             :  real(dp)  :: eigen2_1tetra(4)
     853                 :             : 
     854                 :             : ! *********************************************************************
     855                 :             : 
     856                 :           0 :  ierr = 0
     857   [ #  #  #  # ]:           0 :  if (nene1 <= 1 .or. nene2 <= 1)  then
     858                 :             :    !'get_dbl_tetra_weight: nene must be at least 2'
     859                 :           0 :    ierr = 1
     860                 :             :    return
     861                 :             :  else
     862                 :           0 :    deltaene1 = (enemax1-enemin1) / (nene1-1)
     863                 :           0 :    deltaene2 = (enemax2-enemin2) / (nene2-1)
     864                 :             :  end if
     865                 :             : 
     866   [ #  #  #  #  :           0 :  TETRA_ALLOCATE(tweight_tmp, (4, nene2, nene1))
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     867   [ #  #  #  #  :           0 :  TETRA_ALLOCATE(dtweightde_tmp, (4, nene2, nene1))
          #  #  #  #  #  
                #  #  # ]
     868                 :             : 
     869                 :             : !print *, "warning: for the moment, heaviside weights are 0. The delta function / DOS weights are the only ones calculated "
     870                 :             : 
     871                 :           0 :  volconst = tetra%vv/4.d0
     872                 :             : 
     873                 :             :  ! for each tetrahedron
     874         [ #  # ]:           0 :  do itetra=1,tetra%ntetra
     875                 :             :    ! these are for 1 tetrahedron only.
     876   [ #  #  #  #  :           0 :    tweight_tmp = zero
                   #  # ]
     877   [ #  #  #  #  :           0 :    dtweightde_tmp = zero
                   #  # ]
     878                 :             : 
     879                 :           0 :    volconst_mult = max_occ*volconst*dble(tetra%tetra_mult(itetra))
     880                 :             : 
     881                 :             :    ! Here we need the original ordering to reference the correct irred kpoints
     882                 :             :    ! ind_k refers to the index in the full k list of the summits of the present tetrahedra
     883                 :             :    ! we can forget the order of the summits within the tetrahedron, because eigen1 fixes that
     884                 :             :    ! order with its increasing value
     885                 :           0 :    ind_k(1) = tetra%tetra_full(1,1,itetra)
     886                 :           0 :    ind_k(2) = tetra%tetra_full(2,1,itetra)
     887                 :           0 :    ind_k(3) = tetra%tetra_full(3,1,itetra)
     888                 :           0 :    ind_k(4) = tetra%tetra_full(4,1,itetra)
     889                 :           0 :    eigen1_1tetra(1) = eigen1_in(ind_k(1))
     890                 :           0 :    eigen1_1tetra(2) = eigen1_in(ind_k(2))
     891                 :           0 :    eigen1_1tetra(3) = eigen1_in(ind_k(3))
     892                 :           0 :    eigen1_1tetra(4) = eigen1_in(ind_k(4))
     893                 :           0 :    call sort_tetra(4,eigen1_1tetra,ind_k,tol14)
     894                 :             : 
     895                 :             :    ! re-sort eigen2 values according to order chosen for eigen1. Eigen2 are _not_ in increasing order!
     896                 :           0 :    eigen2_1tetra(1) = eigen2_in(ind_k(1))
     897                 :           0 :    eigen2_1tetra(2) = eigen2_in(ind_k(2))
     898                 :           0 :    eigen2_1tetra(3) = eigen2_in(ind_k(3))
     899                 :           0 :    eigen2_1tetra(4) = eigen2_in(ind_k(4))
     900                 :             : 
     901                 :             :    ! the epsilons are energy differences for the two eigenvalue sets
     902                 :           0 :    epsilon1 = zero
     903                 :           0 :    epsilon2 = zero
     904         [ #  # ]:           0 :    do ieps1 = 1, 4
     905         [ #  # ]:           0 :      do ieps2 = ieps1+1, 4
     906                 :           0 :        epsilon1(ieps1,ieps2) = eigen1_1tetra(ieps1)-eigen1_1tetra(ieps2)
     907                 :           0 :        epsilon1(ieps2,ieps1) = -epsilon1(ieps1,ieps2)
     908                 :           0 :        epsilon2(ieps1,ieps2) = eigen2_1tetra(ieps1)-eigen2_1tetra(ieps2)
     909                 :           0 :        epsilon2(ieps2,ieps1) = -epsilon2(ieps1,ieps2)
     910                 :             :      end do
     911                 :             :    end do
     912                 :             : 
     913                 :             :    ! we precalculate the inverses to avoid doing tons of divisions in the energy loops below
     914                 :             :    ! Allen formulae only require the inverses of the differences of eigen1 + the a b c below
     915                 :           0 :    inv_epsilon1 = zero
     916         [ #  # ]:           0 :    do ieps1 = 1, 4
     917         [ #  # ]:           0 :      do ieps2 = ieps1+1, 4
     918         [ #  # ]:           0 :        if (abs(epsilon1(ieps1,ieps2)) > tol14) then
     919                 :           0 :          inv_epsilon1(ieps1,ieps2) = 1.d0 / epsilon1(ieps1,ieps2)
     920                 :           0 :          inv_epsilon1(ieps2,ieps1) = -inv_epsilon1(ieps1,ieps2)
     921                 :             :        end if
     922                 :             :      end do
     923                 :             :    end do
     924                 :             : 
     925                 :             :    ! these bounds determine the intervals for Omega in Allen paper, and cases A, B, C
     926                 :           0 :    nn1_1 = int((eigen1_1tetra(1)-enemin1)/deltaene1)+1
     927                 :           0 :    nn1_2 = int((eigen1_1tetra(2)-enemin1)/deltaene1)+1
     928                 :           0 :    nn1_3 = int((eigen1_1tetra(3)-enemin1)/deltaene1)+1
     929                 :           0 :    nn1_4 = int((eigen1_1tetra(4)-enemin1)/deltaene1)+1
     930                 :             : 
     931                 :           0 :    nn1_1 = max(1,nn1_1)
     932                 :           0 :    nn1_1 = min(nn1_1,nene1)
     933                 :           0 :    nn1_2 = max(1,nn1_2)
     934                 :           0 :    nn1_2 = min(nn1_2,nene1)
     935                 :           0 :    nn1_3 = max(1,nn1_3)
     936                 :           0 :    nn1_3 = min(nn1_3,nene1)
     937                 :           0 :    nn1_4 = max(1,nn1_4)
     938                 :           0 :    nn1_4 = min(nn1_4,nene1)
     939                 :             : 
     940                 :             :    ! calculate Allen a_i b_i and c_i parameters
     941                 :             :    ! sort the a_i b_i c_i
     942                 :             :    !
     943                 :             :    ! NOTE: indices here go from 1 to 4 instead of 0 to 3 as in Allen...
     944                 :           0 :    aa(1) = epsilon2(2,1) * inv_epsilon1(2,1)
     945                 :           0 :    aa(2) = epsilon2(3,1) * inv_epsilon1(3,1)
     946                 :           0 :    aa(3) = epsilon2(4,1) * inv_epsilon1(4,1)
     947                 :           0 :    ind_a = (/2,3,4/)
     948                 :           0 :    call sort_tetra(3,aa,ind_a,tol14)
     949                 :             :    ! aa are now in order a_s a_m a_l !!! Preserve the hash function ind_a to order the positions of k below
     950                 :           0 :    delaa(1) = aa(2)-aa(1)
     951                 :           0 :    delaa(2) = aa(3)-aa(1)
     952                 :           0 :    delaa(3) = aa(3)-aa(2)
     953                 :           0 :    inv_delaa = zero
     954         [ #  # ]:           0 :    if(delaa(1)> tol14) inv_delaa(1)= 1.0d0 / delaa(1)
     955         [ #  # ]:           0 :    if(delaa(2)> tol14) inv_delaa(2)= 1.0d0 / delaa(2)
     956         [ #  # ]:           0 :    if(delaa(3)> tol14) inv_delaa(3)= 1.0d0 / delaa(3)
     957                 :             : 
     958                 :           0 :    bb(1) = epsilon2(1,2) * inv_epsilon1(1,2)
     959                 :           0 :    bb(2) = epsilon2(3,2) * inv_epsilon1(3,2)
     960                 :           0 :    bb(3) = epsilon2(4,2) * inv_epsilon1(4,2)
     961                 :           0 :    ind_b = (/1,3,4/)
     962                 :           0 :    call sort_tetra(3,bb,ind_b,tol14)
     963                 :           0 :    delbb(1) = bb(2)-bb(1)
     964                 :           0 :    delbb(2) = bb(3)-bb(1)
     965                 :           0 :    delbb(3) = bb(3)-bb(2)
     966                 :           0 :    inv_delbb = zero
     967         [ #  # ]:           0 :    if(delbb(1)> tol14) inv_delbb(1)= 1.0d0 / delbb(1)
     968         [ #  # ]:           0 :    if(delbb(2)> tol14) inv_delbb(2)= 1.0d0 / delbb(2)
     969         [ #  # ]:           0 :    if(delbb(3)> tol14) inv_delbb(3)= 1.0d0 / delbb(3)
     970                 :             : 
     971                 :           0 :    cc(1) = epsilon2(1,4) * inv_epsilon1(1,4)
     972                 :           0 :    cc(2) = epsilon2(2,4) * inv_epsilon1(2,4)
     973                 :           0 :    cc(3) = epsilon2(3,4) * inv_epsilon1(3,4)
     974                 :           0 :    ind_c = (/1,2,3/)
     975                 :           0 :    call sort_tetra(3,cc,ind_c,tol14)
     976                 :           0 :    delcc(1) = cc(2)-cc(1)
     977                 :           0 :    delcc(2) = cc(3)-cc(1)
     978                 :           0 :    delcc(3) = cc(3)-cc(2)
     979                 :           0 :    inv_delcc = zero
     980         [ #  # ]:           0 :    if(delcc(1)> tol14) inv_delcc(1)= 1.0d0 / delcc(1)
     981         [ #  # ]:           0 :    if(delcc(2)> tol14) inv_delcc(2)= 1.0d0 / delcc(2)
     982         [ #  # ]:           0 :    if(delcc(3)> tol14) inv_delcc(3)= 1.0d0 / delcc(3)
     983                 :             : 
     984                 :             :    !----------------------------------------------------------------------
     985                 :             :    ! start main loop A B C over eps1
     986                 :             :    !----------------------------------------------------------------------
     987                 :             : 
     988                 :             :    !
     989                 :             :    !  interval enemin1 < eps1 < e1 nothing to do
     990                 :             :    !
     991                 :             :    !
     992                 :             :    !  interval e1 < eps1 < e3   CASE A in Allen + first term in B
     993                 :             :    !
     994                 :             :    ! NB: eps1 is not updated inside the loop, only between the loops
     995                 :           0 :    eps1 = enemin1+nn1_1*deltaene1
     996                 :           0 :    deleps1 = eps1-eigen1_1tetra(1) ! this is Omega - omega_0
     997                 :           0 :    dccde1_pre = 6.d0*volconst_mult*inv_epsilon1(2,1)*inv_epsilon1(3,1)*inv_epsilon1(4,1)
     998                 :             : 
     999                 :             :    ! note we go to nn1_3
    1000         [ #  # ]:           0 :    do ieps1=nn1_1+1,nn1_3
    1001                 :             : 
    1002                 :           0 :      dccde1 = dccde1_pre * deleps1  ! this is f_0(Omega)*6*v
    1003                 :             : 
    1004                 :             :      ! at fixed ieps1 we can find the pivot indices for the ieps2 loop
    1005                 :           0 :      nn2_1 = int((eigen2_1tetra(1)+deleps1*aa(1) -enemin2)/deltaene2)+1
    1006                 :           0 :      nn2_2 = int((eigen2_1tetra(1)+deleps1*aa(2) -enemin2)/deltaene2)+1
    1007                 :           0 :      nn2_3 = int((eigen2_1tetra(1)+deleps1*aa(3) -enemin2)/deltaene2)+1
    1008                 :             : 
    1009                 :           0 :      nn2_1 = max(1,nn2_1)
    1010                 :           0 :      nn2_1 = min(nn2_1,nene2)
    1011                 :           0 :      nn2_2 = max(1,nn2_2)
    1012                 :           0 :      nn2_2 = min(nn2_2,nene2)
    1013                 :           0 :      nn2_3 = max(1,nn2_3)
    1014                 :           0 :      nn2_3 = min(nn2_3,nene2)
    1015                 :             : 
    1016                 :           0 :      inv_deleps1 = 1.0d0 / deleps1
    1017                 :             : 
    1018                 :           0 :      eps2 = enemin2+nn2_1*deltaene2 ! this is E
    1019                 :           0 :      deleps2 = eps2 - eigen2_1tetra(1) ! this is E-epsilon_0
    1020                 :             : 
    1021                 :             :      !-----------------------------------------------------------------------
    1022                 :             :      ! This is case AI
    1023                 :             :      !-----------------------------------------------------------------------
    1024         [ #  # ]:           0 :      do ieps2 = nn2_1+1, nn2_2
    1025                 :             :        ! calculate running value of del "a"  = a-a_s: first term should really mix eps1 and eps2
    1026                 :           0 :        delaa0 = deleps2*inv_deleps1 - aa(1) ! a - a_s
    1027                 :             : 
    1028                 :           0 :        ii0 = dccde1*delaa0*inv_delaa(1)*inv_delaa(2) ! this is I_0(Omega E)
    1029                 :             : 
    1030                 :             :        dtweightde_tmp(1,ieps2,ieps1) = dtweightde_tmp(1,ieps2,ieps1) + &
    1031                 :             : &         ii0*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_a(1),1)* &
    1032                 :             : &                 (-2.0d0 + delaa0*inv_delaa(1)*epsilon1(ind_a(2),ind_a(1))*inv_epsilon1(ind_a(2),1) &
    1033                 :           0 : &                         + delaa0*inv_delaa(2)*epsilon1(ind_a(3),ind_a(1))*inv_epsilon1(ind_a(3),1)))
    1034                 :             :        dtweightde_tmp(ind_a(1),ieps2,ieps1) = dtweightde_tmp(ind_a(1),ieps2,ieps1) + &
    1035                 :           0 : &         ii0*0.5d0*deleps1*inv_epsilon1(ind_a(1),1)*(2.0d0 - delaa0*inv_delaa(1) - delaa0*inv_delaa(2))
    1036                 :             :        dtweightde_tmp(ind_a(2),ieps2,ieps1) = dtweightde_tmp(ind_a(2),ieps2,ieps1) + &
    1037                 :           0 : &         ii0*0.5d0*delaa0*inv_delaa(1)*deleps1*inv_epsilon1(ind_a(2),1)
    1038                 :             :        dtweightde_tmp(ind_a(3),ieps2,ieps1) = dtweightde_tmp(ind_a(3),ieps2,ieps1) + &
    1039                 :           0 : &         ii0*0.5d0*delaa0*inv_delaa(2)*deleps1*inv_epsilon1(ind_a(3),1)
    1040                 :           0 :        deleps2 = deleps2 + deltaene2
    1041                 :             :      end do
    1042                 :             : 
    1043                 :             : 
    1044                 :           0 :      eps2 = enemin2+nn2_2*deltaene2 ! this is E
    1045                 :           0 :      deleps2 = eps2 - eigen2_1tetra(1)  ! E-E_0
    1046                 :             : 
    1047                 :             :      !-----------------------------------------------------------------------
    1048                 :             :      ! This is case AII
    1049                 :             :      !-----------------------------------------------------------------------
    1050         [ #  # ]:           0 :      do ieps2 = nn2_2+1, nn2_3
    1051                 :             :        ! calculate running value of del "a"  = a_l-a: first term should really mix eps1 and eps2
    1052                 :           0 :        delaa0 = aa(3) - deleps2*inv_deleps1 ! a_l - a
    1053                 :             : 
    1054                 :           0 :        ii0 = dccde1*delaa0*inv_delaa(3)*inv_delaa(2) ! this is I_0(Omega E)
    1055                 :             : 
    1056                 :             :        dtweightde_tmp(1,ieps2,ieps1) = dtweightde_tmp(1,ieps2,ieps1) + &
    1057                 :             : &         ii0*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_a(3),1)* &
    1058                 :             : &                 (-2.0d0 + delaa0*inv_delaa(3)*epsilon1(ind_a(2),ind_a(3))*inv_epsilon1(ind_a(2),1) &
    1059                 :           0 : &                         + delaa0*inv_delaa(2)*epsilon1(ind_a(1),ind_a(3))*inv_epsilon1(ind_a(1),1)))
    1060                 :             :        dtweightde_tmp(ind_a(3),ieps2,ieps1) = dtweightde_tmp(ind_a(3),ieps2,ieps1) + &
    1061                 :           0 : &         ii0*0.5d0*deleps1*inv_epsilon1(ind_a(3),1)*(2.0d0 - delaa0*inv_delaa(3) - delaa0*inv_delaa(2))
    1062                 :             :        dtweightde_tmp(ind_a(2),ieps2,ieps1) = dtweightde_tmp(ind_a(2),ieps2,ieps1) + &
    1063                 :           0 : &         ii0*0.5d0*delaa0*inv_delaa(3)*deleps1*inv_epsilon1(ind_a(2),1)
    1064                 :             :        dtweightde_tmp(ind_a(1),ieps2,ieps1) = dtweightde_tmp(ind_a(1),ieps2,ieps1) + &
    1065                 :           0 : &         ii0*0.5d0*delaa0*inv_delaa(2)*deleps1*inv_epsilon1(ind_a(1),1)
    1066                 :             : 
    1067                 :           0 :        deleps2 = deleps2 + deltaene2
    1068                 :             :      end do
    1069                 :           0 :      deleps1 = deleps1 + deltaene1
    1070                 :             :    end do
    1071                 :             :    !
    1072                 :             :    !  interval e2 < eps < e3
    1073                 :             :    !
    1074                 :           0 :    eps1 = eps1 + (nn1_2-nn1_1)*deltaene1
    1075                 :             : 
    1076                 :           0 :    deleps1 = eps1-eigen1_1tetra(2) ! Omega - omega_1
    1077                 :             : 
    1078                 :           0 :    dccde1_pre = 6.d0*volconst_mult*inv_epsilon1(2,1)*inv_epsilon1(3,2)*inv_epsilon1(4,2) ! f1 function
    1079         [ #  # ]:           0 :    do ieps1=nn1_2+1,nn1_3
    1080                 :             : 
    1081                 :           0 :      dccde1 = dccde1_pre * deleps1 ! f2(Omega) * 6 * v
    1082                 :             : 
    1083                 :             :      ! at fixed ieps1 we can find the pivot indices for the ieps2 loop
    1084                 :           0 :      nn2_1 = int((eigen2_1tetra(2)+deleps1*bb(1) -enemin2)/deltaene2)+1
    1085                 :           0 :      nn2_2 = int((eigen2_1tetra(2)+deleps1*bb(2) -enemin2)/deltaene2)+1
    1086                 :           0 :      nn2_3 = int((eigen2_1tetra(2)+deleps1*bb(3) -enemin2)/deltaene2)+1
    1087                 :             : 
    1088                 :           0 :      nn2_1 = max(1,nn2_1)
    1089                 :           0 :      nn2_1 = min(nn2_1,nene2)
    1090                 :           0 :      nn2_2 = max(1,nn2_2)
    1091                 :           0 :      nn2_2 = min(nn2_2,nene2)
    1092                 :           0 :      nn2_3 = max(1,nn2_3)
    1093                 :           0 :      nn2_3 = min(nn2_3,nene2)
    1094                 :             : 
    1095                 :           0 :      inv_deleps1 = 1.0d0 / deleps1
    1096                 :             : 
    1097                 :           0 :      eps2 = enemin2+nn2_1*deltaene2 ! starting value for E
    1098                 :           0 :      deleps2 = eps2 - eigen2_1tetra(2) ! E - epsilon_1
    1099                 :             : 
    1100                 :             :      !-----------------------------------------------------------------------
    1101                 :             :      ! This is case BI
    1102                 :             :      !-----------------------------------------------------------------------
    1103         [ #  # ]:           0 :      do ieps2 = nn2_1+1, nn2_2
    1104                 :             :        ! calculate running value of del "b"  = b-b_s: first term should really mix eps1 and eps2
    1105                 :           0 :        delbb0 = deleps2*inv_deleps1 - bb(1)
    1106                 :             : 
    1107                 :           0 :        ii1 = dccde1*delbb0*inv_delbb(1)*inv_delbb(2) ! this is I_1(Omega E)
    1108                 :             : 
    1109                 :             :        ! note negative sign here - we are correcting the I0 a0 term already calculated above
    1110                 :             :        dtweightde_tmp(2,ieps2,ieps1) = dtweightde_tmp(2,ieps2,ieps1) - &
    1111                 :             : &         ii1*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_b(1),2)* &
    1112                 :             : &                 (-2.0d0 + delbb0*inv_delbb(1)*epsilon1(ind_b(2),ind_b(1))*inv_epsilon1(ind_b(2),2) &
    1113                 :           0 : &                         + delbb0*inv_delbb(2)*epsilon1(ind_b(3),ind_b(1))*inv_epsilon1(ind_b(3),2)))
    1114                 :             :        dtweightde_tmp(ind_b(1),ieps2,ieps1) = dtweightde_tmp(ind_b(1),ieps2,ieps1) - &
    1115                 :           0 : &         ii1*0.5d0*deleps1*inv_epsilon1(ind_b(1),2)*(2.0d0 - delbb0*inv_delbb(1) - delbb0*inv_delbb(2))
    1116                 :             :        dtweightde_tmp(ind_b(2),ieps2,ieps1) = dtweightde_tmp(ind_b(2),ieps2,ieps1) - &
    1117                 :           0 : &         ii1*0.5d0*delbb0*inv_delbb(1)*deleps1*inv_epsilon1(ind_b(2),2)
    1118                 :             :        dtweightde_tmp(ind_b(3),ieps2,ieps1) = dtweightde_tmp(ind_b(3),ieps2,ieps1) - &
    1119                 :           0 : &         ii1*0.5d0*delbb0*inv_delbb(2)*deleps1*inv_epsilon1(ind_b(3),2)
    1120                 :           0 :        deleps2 = deleps2 + deltaene2
    1121                 :             :      end do
    1122                 :             : 
    1123                 :           0 :      eps2 = enemin2+nn2_2*deltaene2
    1124                 :           0 :      deleps2 = eps2 - eigen2_1tetra(2)
    1125                 :             : 
    1126                 :             :      !-----------------------------------------------------------------------
    1127                 :             :      ! This is case BII
    1128                 :             :      !-----------------------------------------------------------------------
    1129         [ #  # ]:           0 :      do ieps2 = nn2_2+1, nn2_3
    1130                 :             :        ! calculate running value of del "b"  = b_l-b: first term should really mix eps1 and eps2
    1131                 :           0 :        delbb0 = bb(3) - deleps2*inv_deleps1
    1132                 :             : 
    1133                 :           0 :        ii1 = dccde1*delbb0*inv_delbb(3)*inv_delbb(2) ! this is I_1(Omega E)
    1134                 :             : 
    1135                 :             :        ! note negative sign here - we are correcting the I0 a0 term already calculated above
    1136                 :             :        dtweightde_tmp(2,ieps2,ieps1) = dtweightde_tmp(2,ieps2,ieps1) - &
    1137                 :             : &         ii1*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_b(3),2)* &
    1138                 :             : &                 (-2.0d0 + delbb0*inv_delbb(3)*epsilon1(ind_b(2),ind_b(3))*inv_epsilon1(ind_b(2),2) &
    1139                 :           0 : &                         + delbb0*inv_delbb(2)*epsilon1(ind_b(1),ind_b(3))*inv_epsilon1(ind_b(1),2)))
    1140                 :             :        dtweightde_tmp(ind_b(3),ieps2,ieps1) = dtweightde_tmp(ind_b(3),ieps2,ieps1) - &
    1141                 :           0 : &         ii1*0.5d0*deleps1*inv_epsilon1(ind_b(3),2)*(2.0d0 - delbb0*inv_delbb(3) - delbb0*inv_delbb(2))
    1142                 :             :        dtweightde_tmp(ind_b(2),ieps2,ieps1) = dtweightde_tmp(ind_b(2),ieps2,ieps1) - &
    1143                 :           0 : &         ii1*0.5d0*delbb0*inv_delbb(3)*deleps1*inv_epsilon1(ind_b(2),2)
    1144                 :             :        dtweightde_tmp(ind_b(1),ieps2,ieps1) = dtweightde_tmp(ind_b(1),ieps2,ieps1) - &
    1145                 :           0 : &         ii1*0.5d0*delbb0*inv_delbb(2)*deleps1*inv_epsilon1(ind_b(1),2)
    1146                 :             : 
    1147                 :           0 :        deleps2 = deleps2 + deltaene2
    1148                 :             :      end do
    1149                 :             : 
    1150                 :           0 :      deleps1 = deleps1 + deltaene1
    1151                 :             :    end do
    1152                 :             : 
    1153                 :             :    !
    1154                 :             :    !  interval e3 < eps < e4
    1155                 :             :    !
    1156                 :           0 :    eps1 = eps1 + (nn1_3-nn1_2)*deltaene1
    1157                 :           0 :    deleps1 = eps1-eigen1_1tetra(4)
    1158                 :           0 :    dccde1_pre = 6.d0*volconst_mult*inv_epsilon1(4,1)*inv_epsilon1(4,2)*inv_epsilon1(4,3)
    1159         [ #  # ]:           0 :    do ieps1=nn1_3+1,nn1_4
    1160                 :             :      ! note - sign from definition of f3
    1161                 :           0 :      dccde1 = -dccde1_pre *  deleps1 ! f3(Omega) * 6 * v
    1162                 :             : 
    1163                 :             :      ! at fixed ieps1 we can find the pivot indices for the ieps2 loop
    1164                 :             :      ! NB: order is inverted for cc because deleps1 is defined negative (Omega is always less than omega_3)
    1165                 :           0 :      nn2_1 = int((eigen2_1tetra(4)+deleps1*cc(3) -enemin2)/deltaene2)+1
    1166                 :           0 :      nn2_2 = int((eigen2_1tetra(4)+deleps1*cc(2) -enemin2)/deltaene2)+1
    1167                 :           0 :      nn2_3 = int((eigen2_1tetra(4)+deleps1*cc(1) -enemin2)/deltaene2)+1
    1168                 :             : 
    1169                 :           0 :      nn2_1 = max(1,nn2_1)
    1170                 :           0 :      nn2_1 = min(nn2_1,nene2)
    1171                 :           0 :      nn2_2 = max(1,nn2_2)
    1172                 :           0 :      nn2_2 = min(nn2_2,nene2)
    1173                 :           0 :      nn2_3 = max(1,nn2_3)
    1174                 :           0 :      nn2_3 = min(nn2_3,nene2)
    1175                 :           0 :      inv_deleps1 = 1.0d0 / deleps1
    1176                 :             : 
    1177                 :           0 :      eps2 = enemin2+nn2_1*deltaene2 ! starting value for E
    1178                 :           0 :      deleps2 = eps2 - eigen2_1tetra(4) ! E - epsilon_3
    1179                 :             : 
    1180                 :             :      !-----------------------------------------------------------------------
    1181                 :             :      ! This is case CII
    1182                 :             :      !-----------------------------------------------------------------------
    1183         [ #  # ]:           0 :      do ieps2 = nn2_1+1, nn2_2
    1184                 :             :        ! calculate running value of del "c"  = c_l-c: first term should really mix eps1 and eps2
    1185                 :           0 :        delcc0 = cc(3) - deleps2*inv_deleps1
    1186                 :             : 
    1187                 :           0 :        ii3 = dccde1*delcc0*inv_delcc(3)*inv_delcc(2) ! this is I_3(Omega E)
    1188                 :             : 
    1189                 :             :        dtweightde_tmp(4,ieps2,ieps1) = dtweightde_tmp(4,ieps2,ieps1) + &
    1190                 :             : &         ii3*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_c(3),4)* &
    1191                 :             : &                 (-2.0d0 + delcc0*inv_delcc(3)*epsilon1(ind_c(2),ind_c(3))*inv_epsilon1(ind_c(2),4) &
    1192                 :           0 : &                         + delcc0*inv_delcc(2)*epsilon1(ind_c(1),ind_c(3))*inv_epsilon1(ind_c(1),4)))
    1193                 :             :        dtweightde_tmp(ind_c(3),ieps2,ieps1) = dtweightde_tmp(ind_c(3),ieps2,ieps1) + &
    1194                 :           0 : &         ii3*0.5d0*deleps1*inv_epsilon1(ind_c(3),4)*(2.0d0 - delcc0*inv_delcc(3) - delcc0*inv_delcc(2))
    1195                 :             :        dtweightde_tmp(ind_c(2),ieps2,ieps1) = dtweightde_tmp(ind_c(2),ieps2,ieps1) + &
    1196                 :           0 : &         ii3*0.5d0*delcc0*inv_delcc(3)*deleps1*inv_epsilon1(ind_c(2),4)
    1197                 :             :        dtweightde_tmp(ind_c(1),ieps2,ieps1) = dtweightde_tmp(ind_c(1),ieps2,ieps1) + &
    1198                 :           0 : &         ii3*0.5d0*delcc0*inv_delcc(2)*deleps1*inv_epsilon1(ind_c(1),4)
    1199                 :             : 
    1200                 :           0 :        deleps2 = deleps2 + deltaene2
    1201                 :             :      end do
    1202                 :             : 
    1203                 :             : 
    1204                 :           0 :      eps2 = enemin2+nn2_2*deltaene2
    1205                 :           0 :      deleps2 = eps2 - eigen2_1tetra(4)
    1206                 :             : 
    1207                 :             :      !-----------------------------------------------------------------------
    1208                 :             :      ! This is case CI
    1209                 :             :      !-----------------------------------------------------------------------
    1210         [ #  # ]:           0 :      do ieps2 = nn2_2+1, nn2_3
    1211                 :             :        ! calculate running value of del "c"  = c-c_s: first term should really mix eps1 and eps2
    1212                 :           0 :        delcc0 = deleps2*inv_deleps1 - cc(1) ! c - c_s
    1213                 :             : 
    1214                 :           0 :        ii3 = dccde1*delcc0*inv_delcc(1)*inv_delcc(2) ! this is I_3(Omega E)
    1215                 :             : 
    1216                 :             :        dtweightde_tmp(4,ieps2,ieps1) = dtweightde_tmp(4,ieps2,ieps1) + &
    1217                 :             : &         ii3*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_c(1),4)* &
    1218                 :             : &                 (-2.0d0 + delcc0*inv_delcc(1)*epsilon1(ind_c(2),ind_c(1))*inv_epsilon1(ind_c(2),4) &
    1219                 :           0 : &                         + delcc0*inv_delcc(2)*epsilon1(ind_c(3),ind_c(1))*inv_epsilon1(ind_c(3),4)))
    1220                 :             :        dtweightde_tmp(ind_c(1),ieps2,ieps1) = dtweightde_tmp(ind_c(1),ieps2,ieps1) + &
    1221                 :           0 : &         ii3*0.5d0*deleps1*inv_epsilon1(ind_c(1),4)*(2.0d0 - delcc0*inv_delcc(1) - delcc0*inv_delcc(2))
    1222                 :             :        dtweightde_tmp(ind_c(2),ieps2,ieps1) = dtweightde_tmp(ind_c(2),ieps2,ieps1) + &
    1223                 :           0 : &         ii3*0.5d0*delcc0*inv_delcc(1)*deleps1*inv_epsilon1(ind_c(2),4)
    1224                 :             :        dtweightde_tmp(ind_c(3),ieps2,ieps1) = dtweightde_tmp(ind_c(3),ieps2,ieps1) + &
    1225                 :           0 : &         ii3*0.5d0*delcc0*inv_delcc(2)*deleps1*inv_epsilon1(ind_c(3),4)
    1226                 :           0 :        deleps2 = deleps2 + deltaene2
    1227                 :             :      end do
    1228                 :             : 
    1229                 :           0 :      deleps1 = deleps1 + deltaene1
    1230                 :             :    end do
    1231                 :             : 
    1232                 :           0 :    eps1 = eps1 + (nn1_4-nn1_3)*deltaene1
    1233                 :             :    !
    1234                 :             :    !
    1235                 :             :    !  interval e4 < eps < enemax
    1236                 :             :    !
    1237                 :           0 :    do ieps1=nn1_4+1,nene1
    1238                 :             :      ! dtweightde unchanged by this tetrahedron
    1239                 :             :    end do
    1240                 :             : 
    1241                 :             :    ! if we have a fully degenerate tetrahedron,
    1242                 :             :    ! 1) the tweight is a Heaviside (step) function, which is correct above, but
    1243                 :             :    ! 2) the dtweightde should contain a Dirac function: add a Gaussian here
    1244                 :             : 
    1245                 :             :    ! TODO: add treatment in double tetra case
    1246                 :             :    !  end degenerate tetrahedron if
    1247                 :             : 
    1248                 :             :    ! the following blas calls are not working systematically, or do not give speed ups, strange...
    1249                 :             :    !call daxpy (nene, 1.d0, dtweightde_tmp(:,1), 1, dtweightde_t(:,ind_ibz(1)), 1)
    1250                 :             :    !call daxpy (nene, 1.d0, dtweightde_tmp(:,2), 1, dtweightde_t(:,ind_ibz(2)), 1)
    1251                 :             :    !call daxpy (nene, 1.d0, dtweightde_tmp(:,3), 1, dtweightde_t(:,ind_ibz(3)), 1)
    1252                 :             :    !call daxpy (nene, 1.d0, dtweightde_tmp(:,4), 1, dtweightde_t(:,ind_ibz(4)), 1)
    1253                 :             : 
    1254         [ #  # ]:           0 :    do ieps2 = 1, nene2
    1255         [ #  # ]:           0 :      dtweightde(ind_k(1),:,ieps2) = dtweightde(ind_k(1),:,ieps2) + dtweightde_tmp(1,ieps2,:)
    1256         [ #  # ]:           0 :      dtweightde(ind_k(2),:,ieps2) = dtweightde(ind_k(2),:,ieps2) + dtweightde_tmp(2,ieps2,:)
    1257         [ #  # ]:           0 :      dtweightde(ind_k(3),:,ieps2) = dtweightde(ind_k(3),:,ieps2) + dtweightde_tmp(3,ieps2,:)
    1258         [ #  # ]:           0 :      dtweightde(ind_k(4),:,ieps2) = dtweightde(ind_k(4),:,ieps2) + dtweightde_tmp(4,ieps2,:)
    1259                 :             :      !tweight(nkpt,nene1,nene2)
    1260                 :             :    end do
    1261                 :             : 
    1262                 :             :  end do ! itetra
    1263                 :             : 
    1264                 :             :  ! transpose: otherwise the data access is crap and the code slows by an order of magnitude
    1265         [ #  # ]:           0 :  TETRA_DEALLOCATE(tweight_tmp)
    1266         [ #  # ]:           0 :  TETRA_DEALLOCATE(dtweightde_tmp)
    1267                 :             : 
    1268                 :             : end subroutine get_dbl_tetra_weight
    1269                 :             : !!***
    1270                 :             : 
    1271                 :             : !!****f* m_tetrahedron/sort_tetra
    1272                 :             : !! NAME
    1273                 :             : !!  sort_tetra
    1274                 :             : !!
    1275                 :             : !! FUNCTION
    1276                 :             : !!  Sort double precision array list(n) into ascending numerical order using Heapsort
    1277                 :             : !!  algorithm, while making corresponding rearrangement of the integer
    1278                 :             : !!  array iperm. Consider that two double precision numbers
    1279                 :             : !!  within tolerance tol are equal.
    1280                 :             : !!
    1281                 :             : !! INPUTS
    1282                 :             : !!  n        intent(in)    dimension of the list
    1283                 :             : !!  tol      intent(in)    numbers within tolerance are equal
    1284                 :             : !!  list(n)  intent(inout) list of double precision numbers to be sorted
    1285                 :             : !!  iperm(n) intent(inout) iperm(i)=i (very important)
    1286                 :             : !!
    1287                 :             : !! OUTPUT
    1288                 :             : !!  list(n)  sorted list
    1289                 :             : !!  iperm(n) index of permutation given the right ascending order
    1290                 :             : !!
    1291                 :             : !! SOURCE
    1292                 :             : 
    1293                 :             : 
    1294                 :       23332 : subroutine sort_tetra(n,list,iperm,tol)
    1295                 :             : 
    1296                 :             :  integer, intent(in) :: n
    1297                 :             :  integer, intent(inout) :: iperm(n)
    1298                 :             :  real(dp), intent(inout) :: list(n)
    1299                 :             :  real(dp), intent(in) :: tol
    1300                 :             : 
    1301                 :             :  integer :: l,ir,iap,i,j
    1302                 :             :  real(dp) :: ap
    1303                 :             :  character(len=500) :: msg
    1304                 :             : 
    1305         [ -  + ]:       23332 :  if (n==1) then
    1306                 :             :    ! Accomodate case of array of length 1: already sorted!
    1307                 :           0 :    return
    1308         [ -  + ]:       23332 :  else if (n<1) then
    1309                 :             :   ! Should not call with n<1
    1310                 :           0 :   write(msg,1000) n
    1311                 :             :   1000  format(/,' sort_tetra has been called with array length n=',i12,/, &
    1312                 :             : &  ' having a value less than 1. This is not allowed.')
    1313                 :           0 :   TETRA_ERROR(msg)
    1314                 :             : 
    1315                 :             :  else ! n>1
    1316                 :             : 
    1317                 :             :   ! Conduct the usual sort
    1318                 :       23332 :   l=n/2+1
    1319                 :       23332 :   ir=n
    1320                 :             : 
    1321                 :      101080 :   do   ! Infinite do-loop
    1322         [ +  + ]:      124412 :    if (l>1) then
    1323                 :       49248 :     l=l-1
    1324                 :       49248 :     ap=list(l)
    1325                 :       49248 :     iap=iperm(l)
    1326                 :             : 
    1327                 :             :    else ! l<=1
    1328                 :       75164 :     ap=list(ir)
    1329                 :       75164 :     iap=iperm(ir)
    1330                 :       75164 :     list(ir)=list(1)
    1331                 :       75164 :     iperm(ir)=iperm(1)
    1332                 :       75164 :     ir=ir-1
    1333                 :             : 
    1334         [ +  + ]:       75164 :     if (ir==1) then
    1335                 :       23332 :      list(1)=ap
    1336                 :       23332 :      iperm(1)=iap
    1337                 :       23332 :      exit   ! This is the end of this algorithm
    1338                 :             :     end if
    1339                 :             :    end if ! l>1
    1340                 :             : 
    1341                 :      101080 :    i=l
    1342                 :      101080 :    j=l+l
    1343                 :             : 
    1344         [ +  + ]:      252290 :    do while (j<=ir)
    1345         [ +  + ]:      151210 :     if (j<ir) then
    1346   [ +  +  +  +  :       92732 :      if ( list(j)<list(j+1)-tol .or.  &
                   +  + ]
    1347                 :      151210 : &        (list(j)<list(j+1)+tol.and.iperm(j)<iperm(j+1))) j=j+1
    1348                 :             :     endif
    1349   [ +  +  +  +  :      252290 :     if (ap<list(j)-tol .or. (ap<list(j)+tol.and.iap<iperm(j))) then
                   +  + ]
    1350                 :      119156 :      list(i)=list(j)
    1351                 :      119156 :      iperm(i)=iperm(j)
    1352                 :      119156 :      i=j
    1353                 :      119156 :      j=j+j
    1354                 :             :     else
    1355                 :       32054 :      j=ir+1
    1356                 :             :     end if
    1357                 :             :    enddo
    1358                 :             : 
    1359                 :      101080 :    list(i)=ap
    1360                 :      101080 :    iperm(i)=iap
    1361                 :             : 
    1362                 :             :   enddo ! End infinite do-loop
    1363                 :             : 
    1364                 :             :  end if ! n>1
    1365                 :             : 
    1366                 :             : end subroutine sort_tetra
    1367                 :             : !!***
    1368                 :             : 
    1369                 :             : !----------------------------------------------------------------------
    1370                 :             : 
    1371                 :             : !!****f* m_tetrahedron/tetralib_has_mpi
    1372                 :             : !! NAME
    1373                 :             : !! tetralib_has_mpi
    1374                 :             : !!
    1375                 :             : !! FUNCTION
    1376                 :             : !! Return True if library has been compiled with MPI support
    1377                 :             : !!
    1378                 :             : !! SOURCE
    1379                 :             : 
    1380                 :           0 : logical function tetralib_has_mpi() result(ans)
    1381                 :             : 
    1382                 :             :   ans = .False.
    1383                 :             : #ifdef HAVE_MPI
    1384                 :           0 :   ans = .True.
    1385                 :             : #endif
    1386                 :             : 
    1387                 :           0 : end function tetralib_has_mpi
    1388                 :             : !!***
    1389                 :             : 
    1390                 :             : !----------------------------------------------------------------------
    1391                 :             : 
    1392                 :             : !!****f* m_tetrahedron/split_work
    1393                 :             : !! NAME
    1394                 :             : !!  split_work
    1395                 :             : !!
    1396                 :             : !! FUNCTION
    1397                 :             : !!  Splits the number of tasks, ntasks, among nprocs processors. Used for the MPI parallelization of simple loops.
    1398                 :             : !!
    1399                 :             : !! INPUTS
    1400                 :             : !!  ntasks=number of tasks
    1401                 :             : !!  comm=MPI communicator.
    1402                 :             : !!
    1403                 :             : !! OUTPUT
    1404                 :             : !!  nprocs=Number of MPI processes in the communicator.
    1405                 :             : !!  my_start,my_stop= indices defining the initial and final task for this processor
    1406                 :             : !!  ierr=Exit status.
    1407                 :             : !!
    1408                 :             : !! NOTES
    1409                 :             : !!  If nprocs>ntasks then :
    1410                 :             : !!    my_start=ntasks+1
    1411                 :             : !!    my_stop=ntask
    1412                 :             : !!
    1413                 :             : !!  In this particular case, loops of the form
    1414                 :             : !!
    1415                 :             : !!  do ii=my_start,my_stop
    1416                 :             : !!   ...
    1417                 :             : !!  end do
    1418                 :             : !!
    1419                 :             : !!  are not executed. Moreover allocation such as foo(my_start:my_stop) will generate a zero-sized array.
    1420                 :             : !!
    1421                 :             : !! SOURCE
    1422                 :             : 
    1423                 :          18 : subroutine split_work(ntasks,comm,nprocs,my_start,my_stop,ierr)
    1424                 :             : 
    1425                 :             : !Arguments ------------------------------------
    1426                 :             :  integer,intent(in)  :: ntasks,comm
    1427                 :             :  integer,intent(out) :: nprocs,my_start,my_stop,ierr
    1428                 :             : 
    1429                 :             : !Local variables-------------------------------
    1430                 :             :  integer :: res,my_rank,block_p1,block,mpierr
    1431                 :             : 
    1432                 :             : ! *************************************************************************
    1433                 :             : 
    1434                 :          18 :  nprocs = 1; my_start = 1; my_stop = ntasks; ierr = 1
    1435                 :             : #ifdef HAVE_MPI
    1436         [ +  - ]:          18 :  call MPI_COMM_SIZE(comm,nprocs,mpierr); if (mpierr /= MPI_SUCCESS) return
    1437         [ +  - ]:          18 :  call MPI_COMM_RANK(comm,my_rank,mpierr); if (mpierr /= MPI_SUCCESS) return
    1438                 :             : 
    1439                 :          18 :  block   = ntasks/nprocs
    1440                 :          18 :  res     = MOD(ntasks,nprocs)
    1441                 :          18 :  block_p1= block+1
    1442                 :             : 
    1443         [ -  + ]:          18 :  if (my_rank<res) then
    1444                 :           0 :    my_start =  my_rank   *block_p1+1
    1445                 :           0 :    my_stop  = (my_rank+1)*block_p1
    1446                 :             :  else
    1447                 :          18 :    my_start = res*block_p1 + (my_rank-res  )*block + 1
    1448                 :          18 :    my_stop  = res*block_p1 + (my_rank-res+1)*block
    1449                 :             :  end if
    1450                 :             : #endif
    1451                 :          18 :  ierr = 0
    1452                 :             : 
    1453                 :             : end subroutine split_work
    1454                 :             : !!***
    1455                 :             : 
    1456                 :             : !----------------------------------------------------------------------
    1457                 :             : 
    1458                 :             : !!****f* m_tetrahedron/get_onetetra_
    1459                 :             : !! NAME
    1460                 :             : !! get_onetetra_
    1461                 :             : !!
    1462                 :             : !! FUNCTION
    1463                 :             : !! Private function to calculate the contributions to the weights due to a single tetrahedron.
    1464                 :             : !! Extracted from get_tetra_weight
    1465                 :             : !!
    1466                 :             : !! SOURCE
    1467                 :             : 
    1468                 :       23328 : pure subroutine get_onetetra_(tetra,itetra,eigen_1tetra,enemin,enemax,max_occ,nene,bcorr, &
    1469                 :       23328 : &  tweight_tmp,dtweightde_tmp)
    1470                 :             : 
    1471                 :             : !Arguments ------------------------------------
    1472                 :             : !scalars
    1473                 :             :  integer,intent(in) :: nene,bcorr,itetra
    1474                 :             :  type(t_tetrahedron), intent(in) :: tetra
    1475                 :             :  real(dp) ,intent(in) :: enemax,enemin,max_occ
    1476                 :             : !arrays
    1477                 :             :  ! MGTODO: This layout is not optimal (lots of cache thrashing, I will optimize it later on)
    1478                 :             :  real(dp), intent(out) ::  tweight_tmp(nene, 4)
    1479                 :             :  real(dp), intent(out) :: dtweightde_tmp(nene, 4)
    1480                 :             :  real(dp),intent(in)  :: eigen_1tetra(4)
    1481                 :             : 
    1482                 :             : !Local variables-------------------------------
    1483                 :             : !  needed for gaussian replacement of Dirac functions
    1484                 :             : !  the three coefficients of the DOS as quadratic form,
    1485                 :             : !    in the interval [eig(ikpt-1), eig(ikpt)]
    1486                 :             : !    for ikpt = 1 we add a point below eigen(1) which doesnt
    1487                 :             : !    contribute to the DOS in any tetrahedron
    1488                 :             : !scalars
    1489                 :             :  integer :: ieps,nn1,nn2,nn3,nn4
    1490                 :             :  real(dp)  :: cc,cc1,cc2,cc3,dcc1de,dcc2de,dcc3de,dccde,deltaene,eps
    1491                 :             :  real(dp)  :: epsilon21,epsilon31,epsilon32,epsilon41,epsilon42,epsilon43
    1492                 :             :  real(dp)  :: gau_prefactor,gau_width,gau_width2,inv_epsilon21,inv_epsilon31,gval
    1493                 :             :  real(dp)  :: inv_epsilon32,inv_epsilon41,inv_epsilon42,inv_epsilon43
    1494                 :             :  real(dp)  :: deleps1, deleps2, deleps3, deleps4
    1495                 :             :  real(dp)  :: invepsum, cc_pre, dccde_pre
    1496                 :             :  real(dp)  :: cc1_pre, cc2_pre, cc3_pre
    1497                 :             :  real(dp)  :: cc_tmp, dccde_tmp
    1498                 :             :  real(dp)  :: dcc1de_pre, dcc2de_pre, dcc3de_pre
    1499                 :             :  real(dp)  :: tmp,volconst,volconst_mult
    1500                 :             : 
    1501                 :             : ! *********************************************************************
    1502                 :             : 
    1503                 :       23328 :  volconst = tetra%vv/4.d0
    1504                 :             : 
    1505                 :       23328 :  deltaene = (enemax-enemin) / (nene-1)
    1506                 :             : 
    1507                 :             :  ! This is output
    1508   [ +  +  +  +  :    37596960 :  tweight_tmp = zero; dtweightde_tmp = zero
             +  +  +  + ]
    1509                 :             : 
    1510                 :       23328 :  volconst_mult = max_occ*volconst*dble(tetra%tetra_mult(itetra))
    1511                 :             : 
    1512                 :             :  ! all notations are from Blochl PRB 49 16223 [[cite:Bloechl1994a]] Appendix B
    1513                 :       23328 :  epsilon21 = eigen_1tetra(2)-eigen_1tetra(1)
    1514                 :       23328 :  epsilon31 = eigen_1tetra(3)-eigen_1tetra(1)
    1515                 :       23328 :  epsilon41 = eigen_1tetra(4)-eigen_1tetra(1)
    1516                 :       23328 :  epsilon32 = eigen_1tetra(3)-eigen_1tetra(2)
    1517                 :       23328 :  epsilon42 = eigen_1tetra(4)-eigen_1tetra(2)
    1518                 :       23328 :  epsilon43 = eigen_1tetra(4)-eigen_1tetra(3)
    1519         [ +  + ]:       23328 :  inv_epsilon21 = zero; if (epsilon21 > tol14) inv_epsilon21 = 1.d0 / epsilon21
    1520         [ +  - ]:       23328 :  inv_epsilon31 = zero; if (epsilon31 > tol14) inv_epsilon31 = 1.d0 / epsilon31
    1521         [ +  - ]:       23328 :  inv_epsilon41 = zero; if (epsilon41 > tol14) inv_epsilon41 = 1.d0 / epsilon41
    1522         [ +  + ]:       23328 :  inv_epsilon32 = zero; if (epsilon32 > tol14) inv_epsilon32 = 1.d0 / epsilon32
    1523         [ +  - ]:       23328 :  inv_epsilon42 = zero; if (epsilon42 > tol14) inv_epsilon42 = 1.d0 / epsilon42
    1524         [ +  + ]:       23328 :  inv_epsilon43 = zero; if (epsilon43 > tol14) inv_epsilon43 = 1.d0 / epsilon43
    1525                 :             : 
    1526                 :       23328 :  nn1 = int((eigen_1tetra(1)-enemin)/deltaene)+1
    1527                 :       23328 :  nn2 = int((eigen_1tetra(2)-enemin)/deltaene)+1
    1528                 :       23328 :  nn3 = int((eigen_1tetra(3)-enemin)/deltaene)+1
    1529                 :       23328 :  nn4 = int((eigen_1tetra(4)-enemin)/deltaene)+1
    1530                 :             : 
    1531                 :       23328 :  nn1 = max(1,nn1)
    1532                 :       23328 :  nn1 = min(nn1,nene)
    1533                 :       23328 :  nn2 = max(1,nn2)
    1534                 :       23328 :  nn2 = min(nn2,nene)
    1535                 :       23328 :  nn3 = max(1,nn3)
    1536                 :       23328 :  nn3 = min(nn3,nene)
    1537                 :       23328 :  nn4 = max(1,nn4)
    1538                 :       23328 :  nn4 = min(nn4,nene)
    1539                 :             : 
    1540                 :       23328 :  eps = enemin+nn1*deltaene
    1541                 :             :  !
    1542                 :             :  !interval enemin < eps < e1 nothing to do
    1543                 :             :  !
    1544                 :             :  !
    1545                 :             :  !interval e1 < eps < e2
    1546                 :             :  !
    1547                 :       23328 :  deleps1 = eps-eigen_1tetra(1)
    1548                 :       23328 :  cc_pre = volconst_mult*inv_epsilon21*inv_epsilon31*inv_epsilon41
    1549                 :       23328 :  invepsum = inv_epsilon21+inv_epsilon31+inv_epsilon41
    1550                 :       23328 :  dccde_pre = 3.d0*volconst_mult*inv_epsilon21*inv_epsilon31*inv_epsilon41
    1551         [ +  + ]:      302416 :  do ieps=nn1+1,nn2
    1552                 :      279088 :    cc = cc_pre * deleps1*deleps1*deleps1
    1553                 :      279088 :    tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + cc*(4.d0-deleps1*invepsum)
    1554                 :      279088 :    tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + cc*deleps1*inv_epsilon21
    1555                 :      279088 :    tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + cc*deleps1*inv_epsilon31
    1556                 :      279088 :    tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + cc*deleps1*inv_epsilon41
    1557                 :             : 
    1558                 :      279088 :    dccde = dccde_pre * deleps1*deleps1
    1559                 :      279088 :    dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + dccde*(4.d0 - deleps1*invepsum) -cc*invepsum
    1560                 :      279088 :    dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + (dccde*deleps1 + cc) * inv_epsilon21
    1561                 :      279088 :    dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + (dccde*deleps1 + cc) * inv_epsilon31
    1562                 :      279088 :    dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + (dccde*deleps1 + cc) * inv_epsilon41
    1563                 :             : 
    1564         [ -  + ]:      279088 :    if (bcorr == 1) then
    1565                 :             :      ! bxu, correction terms based on Bloechl's paper
    1566                 :             :      tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
    1567                 :           0 : &     4.d0*dccde_pre*deleps1*deleps1*(epsilon21+epsilon31+epsilon41)/40.d0
    1568                 :             :      tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
    1569                 :           0 : &     4.d0*dccde_pre*deleps1*deleps1*(-epsilon21+epsilon32+epsilon42)/40.d0
    1570                 :             :      tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
    1571                 :           0 : &     4.d0*dccde_pre*deleps1*deleps1*(-epsilon31-epsilon32+epsilon43)/40.d0
    1572                 :             :      tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
    1573                 :           0 : &     4.d0*dccde_pre*deleps1*deleps1*(-epsilon41-epsilon42-epsilon43)/40.d0
    1574                 :             : 
    1575                 :             :      dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + &
    1576                 :           0 : &     8.d0*dccde_pre*deleps1*(epsilon21+epsilon31+epsilon41)/40.d0
    1577                 :             :      dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + &
    1578                 :           0 : &     8.d0*dccde_pre*deleps1*(-epsilon21+epsilon32+epsilon42)/40.d0
    1579                 :             :      dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + &
    1580                 :           0 : &     8.d0*dccde_pre*deleps1*(-epsilon31-epsilon32+epsilon43)/40.d0
    1581                 :             :      dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + &
    1582                 :           0 : &     8.d0*dccde_pre*deleps1*(-epsilon41-epsilon42-epsilon43)/40.d0
    1583                 :             :    end if
    1584                 :             : 
    1585                 :      302416 :    deleps1 = deleps1 + deltaene
    1586                 :             :  end do
    1587                 :             : 
    1588                 :       23328 :  eps = eps + (nn2-nn1)*deltaene
    1589                 :             :  !
    1590                 :             :  !  interval e2 < eps < e3
    1591                 :             :  !
    1592                 :       23328 :  deleps1 = eps-eigen_1tetra(1)
    1593                 :       23328 :  deleps2 = eps-eigen_1tetra(2)
    1594                 :       23328 :  deleps3 = eigen_1tetra(3)-eps
    1595                 :       23328 :  deleps4 = eigen_1tetra(4)-eps
    1596                 :             : 
    1597                 :       23328 :  cc1_pre = volconst_mult*inv_epsilon31*inv_epsilon41
    1598                 :       23328 :  cc2_pre = volconst_mult*inv_epsilon41*inv_epsilon32*inv_epsilon31
    1599                 :       23328 :  cc3_pre = volconst_mult*inv_epsilon42*inv_epsilon32*inv_epsilon41
    1600                 :             : 
    1601                 :       23328 :  dcc1de_pre = 2.d0*cc1_pre
    1602                 :       23328 :  dcc2de_pre = cc2_pre
    1603                 :       23328 :  dcc3de_pre = cc3_pre
    1604         [ +  + ]:      228264 :  do ieps=nn2+1,nn3
    1605                 :      204936 :    cc1 = cc1_pre * deleps1*deleps1
    1606                 :      204936 :    cc2 = cc2_pre * deleps1*deleps2*deleps3
    1607                 :      204936 :    cc3 = cc3_pre * deleps2*deleps2*deleps4
    1608                 :             : 
    1609                 :             :    tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
    1610                 :      204936 : &   cc1 + (cc1+cc2)*deleps3*inv_epsilon31 + (cc1+cc2+cc3)*deleps4*inv_epsilon41
    1611                 :             :    tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
    1612                 :      204936 : &   cc1+cc2+cc3+(cc2+cc3)*deleps3*inv_epsilon32 + cc3*deleps4*inv_epsilon42
    1613                 :             :    tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
    1614                 :      204936 : &   (cc1+cc2)*deleps1*inv_epsilon31 + (cc2+cc3)*deleps2*inv_epsilon32
    1615                 :             :    tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
    1616                 :      204936 : &   (cc1+cc2+cc3)*deleps1*inv_epsilon41 + cc3*deleps2*inv_epsilon42
    1617                 :             : 
    1618                 :             : 
    1619                 :      204936 :    dcc1de = dcc1de_pre * deleps1
    1620                 :      204936 :    dcc2de = dcc2de_pre * (-deleps1*deleps2  +deleps1*deleps3  +deleps2*deleps3)
    1621                 :      204936 :    dcc3de = dcc3de_pre * (2.d0*deleps2*deleps4  -deleps2*deleps2)
    1622                 :             : 
    1623                 :             :    dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) &
    1624                 :             : &   + dcc1de &
    1625                 :             : &   + ((dcc1de+dcc2de)*deleps3 -(cc1+cc2)) * inv_epsilon31 &
    1626                 :      204936 : &   + ((dcc1de+dcc2de+dcc3de)*deleps4 -(cc1+cc2+cc3)) * inv_epsilon41
    1627                 :             :    dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) &
    1628                 :             : &   + dcc1de+dcc2de+dcc3de &
    1629                 :             : &   + ((dcc2de+dcc3de)*deleps3 -(cc2+cc3) ) * inv_epsilon32 &
    1630                 :      204936 : &   + (dcc3de*deleps4  -cc3 ) * inv_epsilon42
    1631                 :             :    dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) &
    1632                 :             : &   + ((dcc1de+dcc2de)*deleps1 + (cc1+cc2) ) * inv_epsilon31 &
    1633                 :      204936 : &   + ((dcc2de+dcc3de)*deleps2 + (cc2+cc3) ) * inv_epsilon32
    1634                 :             :    dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) &
    1635                 :             : &   + ((dcc1de+dcc2de+dcc3de)*deleps1 + (cc1+cc2+cc3) ) * inv_epsilon41 &
    1636                 :      204936 : &   + (dcc3de*deleps2 + cc3) * inv_epsilon42
    1637                 :             : 
    1638         [ -  + ]:      204936 :  if (bcorr == 1) then
    1639                 :             :    ! bxu, correction terms based on Bloechl's paper
    1640                 :             :    ! The correction terms may cause the dtweightde become negative
    1641                 :             :    tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
    1642                 :             : &   4.d0*cc1_pre* &
    1643                 :             : &   (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
    1644                 :           0 : &   (epsilon21+epsilon31+epsilon41)/40.d0
    1645                 :             :    tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
    1646                 :             : &   4.d0*cc1_pre* &
    1647                 :             : &   (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
    1648                 :           0 : &   (-epsilon21+epsilon32+epsilon42)/40.d0
    1649                 :             :    tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
    1650                 :             : &   4.d0*cc1_pre* &
    1651                 :             : &   (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
    1652                 :           0 : &   (-epsilon31-epsilon32+epsilon43)/40.d0
    1653                 :             :    tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
    1654                 :             : &   4.d0*cc1_pre* &
    1655                 :             : &   (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
    1656                 :           0 : &   (-epsilon41-epsilon42-epsilon43)/40.d0
    1657                 :             : 
    1658                 :             :    dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + &
    1659                 :             : &   4.d0*cc1_pre* &
    1660                 :             : &   (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
    1661                 :           0 : &   (epsilon21+epsilon31+epsilon41)/40.d0
    1662                 :             :    dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + &
    1663                 :             : &   4.d0*cc1_pre* &
    1664                 :             : &   (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
    1665                 :           0 : &   (-epsilon21+epsilon32+epsilon42)/40.d0
    1666                 :             :    dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + &
    1667                 :             : &   4.d0*cc1_pre* &
    1668                 :             : &   (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
    1669                 :           0 : &   (-epsilon31-epsilon32+epsilon43)/40.d0
    1670                 :             :    dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + &
    1671                 :             : &   4.d0*cc1_pre* &
    1672                 :             : &   (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
    1673                 :           0 : &   (-epsilon41-epsilon42-epsilon43)/40.d0
    1674                 :             :   end if
    1675                 :             : 
    1676                 :      204936 :   deleps1 = deleps1 + deltaene
    1677                 :      204936 :   deleps2 = deleps2 + deltaene
    1678                 :      204936 :   deleps3 = deleps3 - deltaene
    1679                 :      228264 :   deleps4 = deleps4 - deltaene
    1680                 :             :  end do
    1681                 :             : 
    1682                 :       23328 :  eps = eps + (nn3-nn2)*deltaene
    1683                 :             :  !
    1684                 :             :  !  interval e3 < eps < e4
    1685                 :             :  !
    1686                 :       23328 :  deleps4 = eigen_1tetra(4)-eps
    1687                 :       23328 :  cc_pre = volconst_mult*inv_epsilon41*inv_epsilon42*inv_epsilon43
    1688                 :       23328 :  invepsum = inv_epsilon41+inv_epsilon42+inv_epsilon43
    1689                 :       23328 :  dccde_pre = -3.d0*cc_pre
    1690         [ +  + ]:      244400 :  do ieps=nn3+1,nn4
    1691                 :      221072 :    cc = cc_pre * deleps4*deleps4*deleps4
    1692                 :      221072 :    cc_tmp = cc * deleps4
    1693                 :      221072 :    tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + volconst_mult - cc_tmp*inv_epsilon41
    1694                 :      221072 :    tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + volconst_mult - cc_tmp*inv_epsilon42
    1695                 :      221072 :    tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + volconst_mult - cc_tmp*inv_epsilon43
    1696                 :      221072 :    tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + volconst_mult - cc*4.d0 + cc_tmp*invepsum
    1697                 :             : 
    1698                 :      221072 :    dccde = dccde_pre * deleps4*deleps4
    1699                 :      221072 :    dccde_tmp = -dccde*deleps4 + cc
    1700                 :      221072 :    dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + dccde_tmp * inv_epsilon41
    1701                 :      221072 :    dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + dccde_tmp * inv_epsilon42
    1702                 :      221072 :    dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + dccde_tmp * inv_epsilon43
    1703                 :      221072 :    dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) - dccde*4.d0 - dccde_tmp*invepsum
    1704                 :             : 
    1705         [ -  + ]:      221072 :    if (bcorr == 1) then
    1706                 :             :      ! bxu, correction terms based on Bloechl's paper
    1707                 :             :      ! The correction terms may cause the dtweightde become negative
    1708                 :             :      tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
    1709                 :           0 : &     12.d0*cc_pre*deleps4*deleps4*(epsilon21+epsilon31+epsilon41)/40.d0
    1710                 :             :      tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
    1711                 :           0 : &     12.d0*cc_pre*deleps4*deleps4*(-epsilon21+epsilon32+epsilon42)/40.d0
    1712                 :             :      tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
    1713                 :           0 : &     12.d0*cc_pre*deleps4*deleps4*(-epsilon31-epsilon32+epsilon43)/40.d0
    1714                 :             :      tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
    1715                 :           0 : &     12.d0*cc_pre*deleps4*deleps4*(-epsilon41-epsilon42-epsilon43)/40.d0
    1716                 :             : 
    1717                 :             :      dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) - &
    1718                 :           0 : &     24.d0*cc_pre*deleps4*(epsilon21+epsilon31+epsilon41)/40.d0
    1719                 :             :      dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) - &
    1720                 :           0 : &     24.d0*cc_pre*deleps4*(-epsilon21+epsilon32+epsilon42)/40.d0
    1721                 :             :      dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) - &
    1722                 :           0 : &     24.d0*cc_pre*deleps4*(-epsilon31-epsilon32+epsilon43)/40.d0
    1723                 :             :      dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) - &
    1724                 :           0 : &     24.d0*cc_pre*deleps4*(-epsilon41-epsilon42-epsilon43)/40.d0
    1725                 :             :    end if
    1726                 :             : 
    1727                 :      244400 :    deleps4 = deleps4 - deltaene
    1728                 :             :  end do
    1729                 :       23328 :  eps = eps + (nn4-nn3)*deltaene
    1730                 :             :  !
    1731                 :             :  !
    1732                 :             :  !  interval e4 < eps < enemax
    1733                 :             :  !
    1734         [ +  + ]:     1429904 :  do ieps=nn4+1,nene
    1735                 :     1406576 :    tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + volconst_mult
    1736                 :     1406576 :    tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + volconst_mult
    1737                 :     1406576 :    tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + volconst_mult
    1738                 :     1429904 :    tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + volconst_mult
    1739                 :             :    ! dtweightde unchanged by this tetrahedron
    1740                 :             :  end do
    1741                 :             : 
    1742                 :             :  !
    1743                 :             :  !  if we have a fully degenerate tetrahedron,
    1744                 :             :  !  1) the tweight is a Heaviside (step) function, which is correct above, but
    1745                 :             :  !  2) the dtweightde should contain a Dirac function: add a Gaussian here
    1746                 :             :  !
    1747         [ -  + ]:       23328 :  if (epsilon41 < tol14) then
    1748                 :             : 
    1749                 :             :    !  to ensure the gaussian will integrate properly:
    1750                 :             :    !  WARNING: this smearing could be problematic if too large
    1751                 :             :    !  and doesnt integrate well if its too small
    1752                 :           0 :    gau_width = 10.0d0*deltaene
    1753                 :           0 :    gau_width2 = 1.0 / gau_width / gau_width
    1754                 :           0 :    gau_prefactor = volconst_mult / gau_width / sqrt(pi)
    1755                 :             :    !
    1756                 :             :    ! average position since bracket for epsilon41 is relatively large
    1757                 :           0 :    cc = (eigen_1tetra(1)+eigen_1tetra(2)+eigen_1tetra(3)+eigen_1tetra(4))/4.d0
    1758                 :           0 :    eps = enemin
    1759         [ #  # ]:           0 :    do ieps=1,nene
    1760                 :           0 :      tmp = eps - cc
    1761                 :           0 :      gval = gau_prefactor*exp(-tmp*tmp*gau_width2)
    1762                 :             :      ! MG TODO: I think this is not correct, because we have divided by 4 so
    1763                 :             :      ! the other points should be accumulated as well.
    1764                 :             :      ! There are however changes in the unit tests if I activate these lines...
    1765                 :             :      !dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + gval
    1766                 :             :      !dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + gval
    1767                 :             :      !dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + gval
    1768                 :           0 :      dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + gval
    1769                 :           0 :      eps = eps + deltaene
    1770                 :             :    end do
    1771                 :             :  end if ! end degenerate tetrahedron if
    1772                 :             : 
    1773                 :       23328 : end subroutine get_onetetra_
    1774                 :             : !!***
    1775                 :             : 
    1776                 :             : !----------------------------------------------------------------------
    1777                 :             : 
    1778                 :             : !!****f* m_tetrahedron/tetra_get_onewk
    1779                 :             : !! NAME
    1780                 :             : !! tetra_get_onewk
    1781                 :             : !!
    1782                 :             : !! FUNCTION
    1783                 :             : !! Calculate integration weights and their derivatives for a single k-point in the IBZ.
    1784                 :             : !!
    1785                 :             : !! INPUTS
    1786                 :             : !! tetra<t_tetrahedron>=Object with tables for tetrahedron method.
    1787                 :             : !! ik_ibz=Index of the k-point in the IBZ array
    1788                 :             : !! bcorr=1 to include Blochl correction else 0.
    1789                 :             : !! nene=number of energies for DOS
    1790                 :             : !! nibz=number of irreducible kpoints
    1791                 :             : !! eigen_ibz(nkibz)=eigenenergies for each k point
    1792                 :             : !! enemin=minimal energy for DOS
    1793                 :             : !! enemax=maximal energy for DOS
    1794                 :             : !! max_occ=maximal occupation number (2 for nsppol=1, 1 for nsppol=2)
    1795                 :             : !!
    1796                 :             : !! OUTPUT
    1797                 :             : !!  weights(nene,2) = integration weights for
    1798                 :             : !!    Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
    1799                 :             : !!    for a given (band, k-point, spin).
    1800                 :             : !!
    1801                 :             : !! SOURCE
    1802                 :             : 
    1803                 :           0 : subroutine tetra_get_onewk(tetra,ik_ibz,bcorr,nene,nkibz,eig_ibz,enemin,enemax,max_occ,weights)
    1804                 :             : 
    1805                 :             : !Arguments ------------------------------------
    1806                 :             : !scalars
    1807                 :             :  integer,intent(in) :: ik_ibz,nene,nkibz,bcorr
    1808                 :             :  type(t_tetrahedron), intent(in) :: tetra
    1809                 :             :  real(dp) ,intent(in) :: enemin,enemax,max_occ
    1810                 :             : !arrays
    1811                 :             :  real(dp),intent(in) :: eig_ibz(nkibz)
    1812                 :             :  real(dp),intent(out) :: weights(nene,2)
    1813                 :             : 
    1814                 :             : !Local variables-------------------------------
    1815                 :             : !scalars
    1816                 :             :  integer :: itetra,ii
    1817                 :             : !arrays
    1818                 :             :  integer :: ind_ibz(4)
    1819                 :           0 :  real(dp) :: tweight_tmp(nene,4),dtweightde_tmp(nene,4),eigen_1tetra(4)
    1820                 :             : 
    1821                 :             : ! *********************************************************************
    1822                 :             : 
    1823   [ #  #  #  # ]:           0 :  weights = zero
    1824                 :             : 
    1825                 :             :  ! For each tetrahedron
    1826         [ #  # ]:           0 :  do itetra=1,tetra%ntetra
    1827                 :             : 
    1828                 :             :    ! Here we need the original ordering to reference the correct irred kpoints
    1829         [ #  # ]:           0 :    ind_ibz(:) = tetra%tetra_full(:,1,itetra)
    1830                 :             :    ! Cycle if this tetra does not contribute to this k-point.
    1831   [ #  #  #  #  :           0 :    if (all(ind_ibz /= ik_ibz)) cycle
                   #  # ]
    1832                 :             : 
    1833                 :             :    ! Sort energies before calling get_onetetra_
    1834         [ #  # ]:           0 :    eigen_1tetra(:) = eig_ibz(ind_ibz(:))
    1835                 :           0 :    call sort_tetra(4, eigen_1tetra, ind_ibz, tol14)
    1836                 :             : 
    1837                 :             :    call get_onetetra_(tetra, itetra, eigen_1tetra, enemin, enemax, max_occ, nene, bcorr, &
    1838                 :           0 :      tweight_tmp, dtweightde_tmp)
    1839                 :             : 
    1840                 :             :    ! Accumulate contributions to ik_ibz (there might be multiple vertexes that map onto ik_ibz)
    1841         [ #  # ]:           0 :    do ii=1,4
    1842         [ #  # ]:           0 :      if (ind_ibz(ii) == ik_ibz) then
    1843         [ #  # ]:           0 :        weights(:,1) = weights(:,1) + dtweightde_tmp(:,ii)
    1844         [ #  # ]:           0 :        weights(:,2) = weights(:,2) + tweight_tmp(:,ii)
    1845                 :             :      end if
    1846                 :             :    end do
    1847                 :             :  end do ! itetra
    1848                 :             : 
    1849                 :           0 : end subroutine tetra_get_onewk
    1850                 :             : !!***
    1851                 :             : 
    1852                 :             : !----------------------------------------------------------------------
    1853                 :             : 
    1854                 :             : !!****f* m_tetrahedron/tetra_get_onewk_wvals
    1855                 :             : !! NAME
    1856                 :             : !! tetra_get_onewk_wvals
    1857                 :             : !!
    1858                 :             : !! FUNCTION
    1859                 :             : !! Calculate integration weights and their derivatives for a single k-point in the IBZ.
    1860                 :             : !!
    1861                 :             : !! INPUTS
    1862                 :             : !! tetra<t_tetrahedron>=Object with tables for tetrahedron method.
    1863                 :             : !! ik_ibz=Index of the k-point in the IBZ array
    1864                 :             : !! bcorr=1 to include Blochl correction else 0.
    1865                 :             : !! nw=number of energies in wvals
    1866                 :             : !! nibz=number of irreducible kpoints
    1867                 :             : !! wvals(nw)=Frequency points.
    1868                 :             : !! eigen_ibz(nkibz)=eigenenergies for each k point
    1869                 :             : !! [wtol]: If present, frequency points that differ by less that wtol are treated as equivalent.
    1870                 :             : !!  and the tetrahedron integration is performed only once per frequency point.
    1871                 :             : !!
    1872                 :             : !! OUTPUT
    1873                 :             : !!  weights(nw,2) = integration weights for
    1874                 :             : !!    Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
    1875                 :             : !!    for a given (band, k-point, spin).
    1876                 :             : !!
    1877                 :             : !! SOURCE
    1878                 :             : 
    1879                 :           0 : subroutine tetra_get_onewk_wvals(tetra, ik_ibz, bcorr, nw, wvals, nkibz, eig_ibz, weights, wtol)
    1880                 :             : 
    1881                 :             : !Arguments ------------------------------------
    1882                 :             : !scalars
    1883                 :             :  integer,intent(in) :: ik_ibz,nw,nkibz,bcorr
    1884                 :             :  real(dp), optional, intent(in) :: wtol
    1885                 :             :  type(t_tetrahedron), intent(in) :: tetra
    1886                 :             : !arrays
    1887                 :             :  real(dp),intent(in) :: wvals(nw)
    1888                 :             :  real(dp),intent(in) :: eig_ibz(nkibz)
    1889                 :             :  real(dp),intent(out) :: weights(nw, 2)
    1890                 :             : 
    1891                 :             : !Local variables-------------------------------
    1892                 :             : !scalars
    1893                 :             :  !integer,save :: done = 0
    1894                 :             :  integer,parameter :: nene=3
    1895                 :             :  integer :: itetra,ii,jj,iw,ie
    1896                 :             :  logical :: samew
    1897                 :             :  real(dp),parameter :: max_occ1 = one
    1898                 :             :  real(dp) :: enemin, enemax
    1899                 :             : !arrays
    1900                 :             :  integer :: ind_ibz(4)
    1901                 :             :  real(dp) :: theta_tmp(nene,4), delta_tmp(nene,4), eigen_1tetra(4)
    1902                 :             : 
    1903                 :             : ! *********************************************************************
    1904                 :             : 
    1905   [ #  #  #  # ]:           0 :  weights = zero
    1906                 :             : 
    1907                 :             :  ! For each tetrahedron
    1908         [ #  # ]:           0 :  do jj=1,tetra%ibz_tetra_count(ik_ibz)
    1909                 :           0 :    itetra = tetra%ibz_tetra_mapping(ik_ibz,jj)
    1910                 :             : 
    1911                 :             :    ! Here we need the original ordering to reference the correct irred kpoints
    1912         [ #  # ]:           0 :    ind_ibz(:) = tetra%tetra_full(:,1,itetra)
    1913                 :             : 
    1914                 :             :    ! Sort energies before calling get_onetetra_
    1915         [ #  # ]:           0 :    eigen_1tetra(:) = eig_ibz(ind_ibz(:))
    1916                 :           0 :    call sort_tetra(4, eigen_1tetra, ind_ibz, tol14)
    1917                 :             : 
    1918         [ #  # ]:           0 :    do iw=1,nw
    1919                 :           0 :      samew = .False.
    1920         [ #  # ]:           0 :      if (present(wtol)) then
    1921         [ #  # ]:           0 :        if (iw > 1) samew = abs(wvals(iw) - wvals(iw - 1)) < wtol
    1922                 :             :      end if
    1923         [ #  # ]:           0 :      if (.not. samew) then
    1924                 :           0 :          enemin = wvals(iw) - 0.01; enemax = wvals(iw) + 0.01
    1925                 :           0 :          ie = nene / 2 + 1
    1926                 :             :          call get_onetetra_(tetra, itetra, eigen_1tetra, enemin, enemax, max_occ1, nene, bcorr, &
    1927                 :           0 :             theta_tmp, delta_tmp)
    1928                 :             :      end if
    1929                 :             : 
    1930                 :             :      ! Accumulate contributions to ik_ibz (there might be multiple vertexes that map onto ik_ibz)
    1931         [ #  # ]:           0 :      do ii=1,4
    1932         [ #  # ]:           0 :        if (ind_ibz(ii) == ik_ibz) then
    1933                 :           0 :          weights(iw, 1) = weights(iw, 1) + delta_tmp(ie, ii)
    1934                 :           0 :          weights(iw, 2) = weights(iw, 2) + theta_tmp(ie, ii)
    1935                 :             :        end if
    1936                 :             :      end do
    1937                 :             :    end do ! iw
    1938                 :             :  end do ! itetra
    1939                 :             : 
    1940                 :           0 : end subroutine tetra_get_onewk_wvals
    1941                 :             : !!***
    1942                 :             : 
    1943                 :             : !----------------------------------------------------------------------
    1944                 :             : 
    1945                 :             : !!****f* m_tetrahedron/tetra_get_onetetra_wvals
    1946                 :             : !! NAME
    1947                 :             : !! tetra_get_onetetra_wvals
    1948                 :             : !!
    1949                 :             : !! FUNCTION
    1950                 :             : !! Calculate integration weights and their derivatives for a single k-point in the IBZ.
    1951                 :             : !!
    1952                 :             : !! INPUTS
    1953                 :             : !! tetra<t_tetrahedron>=Object with tables for tetrahedron method.
    1954                 :             : !! ik_ibz=Index of the k-point in the IBZ array
    1955                 :             : !! bcorr=1 to include Blochl correction else 0.
    1956                 :             : !! nw=number of energies in wvals
    1957                 :             : !! nibz=number of irreducible kpoints
    1958                 :             : !! wvals(nw)=Frequency points.
    1959                 :             : !! eigen_ibz(nkibz)=eigenenergies for each k point
    1960                 :             : !! [wtol]: If present, frequency points that differ by less that wtol are treated as equivalent.
    1961                 :             : !!  and the tetrahedron integration is performed only once per frequency point.
    1962                 :             : !!
    1963                 :             : !! OUTPUT
    1964                 :             : !!  weights(nw,2) = integration weights for
    1965                 :             : !!    Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
    1966                 :             : !!    for a given (band, k-point, spin).
    1967                 :             : !!
    1968                 :             : !! SOURCE
    1969                 :             : 
    1970                 :           0 : subroutine tetra_get_onetetra_wvals(tetra, itetra, eigen_1tetra, bcorr, nw, wvals, weights, wtol)
    1971                 :             : 
    1972                 :             : !Arguments ------------------------------------
    1973                 :             : !scalars
    1974                 :             :  integer,intent(in) :: nw,bcorr
    1975                 :             :  real(dp), optional, intent(in) :: wtol
    1976                 :             :  type(t_tetrahedron), intent(in) :: tetra
    1977                 :             : !arrays
    1978                 :             :  real(dp),intent(in) :: wvals(nw)
    1979                 :             :  real(dp),intent(out) :: weights(nw, 2, 4)
    1980                 :             : 
    1981                 :             : !Local variables-------------------------------
    1982                 :             : !scalars
    1983                 :             :  !integer,save :: done = 0
    1984                 :             :  integer,parameter :: nene3=3
    1985                 :             :  integer :: itetra,ii,idx,iw,ie
    1986                 :             :  integer :: ind(4)
    1987                 :             :  logical :: samew
    1988                 :             :  real(dp),parameter :: max_occ1 = one
    1989                 :             :  real(dp) :: enemin, enemax
    1990                 :             : !arrays
    1991                 :             :  real(dp) :: theta_tmp(nene3,4), delta_tmp(nene3,4), eigen_1tetra(4)
    1992                 :             : 
    1993                 :             : ! *********************************************************************
    1994                 :             : 
    1995                 :           0 :  ind = [1,2,3,4]
    1996                 :           0 :  call sort_tetra(4, eigen_1tetra, ind, tol14)
    1997   [ #  #  #  #  :           0 :  weights = 0
                   #  # ]
    1998                 :             : 
    1999                 :             :  !for all the frequencies
    2000         [ #  # ]:           0 :  do iw=1,nw
    2001                 :           0 :    samew = .False.
    2002         [ #  # ]:           0 :    if (present(wtol)) then
    2003         [ #  # ]:           0 :      if (iw > 1) samew = abs(wvals(iw) - wvals(iw - 1)) < wtol
    2004                 :             :    end if
    2005         [ #  # ]:           0 :    if (.not. samew) then
    2006                 :           0 :      enemin = wvals(iw) - 0.01
    2007                 :           0 :      enemax = wvals(iw) + 0.01
    2008                 :           0 :      ie = nene3 / 2 + 1
    2009                 :             :      call get_onetetra_(tetra, itetra, eigen_1tetra, enemin, enemax, max_occ1, nene3, bcorr, &
    2010                 :           0 :         theta_tmp, delta_tmp)
    2011                 :             :    end if
    2012                 :             : 
    2013                 :             :    ! Accumulate contributions to ik_ibz (there might be multiple vertexes that map onto ik_ibz)
    2014         [ #  # ]:           0 :    do ii=1,4
    2015                 :           0 :      idx = ind(ii)
    2016                 :           0 :      weights(iw, 1, idx) = weights(iw, 1, idx) + delta_tmp(ie, ii)
    2017                 :           0 :      weights(iw, 2, idx) = weights(iw, 2, idx) + theta_tmp(ie, ii)
    2018                 :             :    end do
    2019                 :             :  end do !iw
    2020                 :             : 
    2021                 :           0 : end subroutine tetra_get_onetetra_wvals
    2022                 :             : !!***
    2023                 :             : 
    2024   [ #  #  #  #  :           0 : end module m_tetrahedron
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    2025                 :             : !!***
        

Generated by: LCOV version 2.3-1