LCOV - code coverage report
Current view: top level - shared/common/src/29_kpoints - m_htetra.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 70.4 % 1081 761
Test Date: 2026-09-21 19:39:32 Functions: 68.2 % 22 15

            Line data    Source code
       1              : !!****m* ABINIT/m_htetra
       2              : !! NAME
       3              : !! m_htetra
       4              : !!
       5              : !! FUNCTION
       6              : !!  Module for tetrahedron integration of DOS and similar quantities
       7              : !!  Uses some functions from a previous implementation by MJV
       8              : !!
       9              : !! COPYRIGHT
      10              : !!  Copyright (C) 2010-2026 ABINIT group (HM,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 more carefully the case of degenerate tethraedron
      17              : !!  2) Add options to get only delta and/or theta ?
      18              : !!
      19              : !! SOURCE
      20              : 
      21              : #if defined HAVE_CONFIG_H
      22              : #include "config.h"
      23              : #endif
      24              : 
      25              : #include "abi_common.h"
      26              : 
      27              : module m_htetra
      28              : 
      29              :  use defs_basis
      30              :  use m_abicore
      31              :  use m_krank
      32              :  use m_xmpi
      33              :  use m_errors
      34              : 
      35              :  use m_fstrings,        only : sjoin, itoa, ftoa
      36              :  use m_numeric_tools,   only : linspace
      37              :  use m_simtet,          only : sim0onei, SIM0TWOI
      38              : 
      39              : implicit none
      40              : 
      41              : private
      42              : !!***
      43              : 
      44              : integer, parameter :: TETRA_SIZE = 6
      45              : integer, parameter :: TETRA_STEP = 6
      46              : 
      47              : !!****t* m_htetra/t_htetra_bucket
      48              : !! NAME
      49              : !! t_htetra_bucket
      50              : !!
      51              : !! FUNCTION
      52              : !! Store a bunch of tetrahedra
      53              : !!
      54              : !! SOURCE
      55              : 
      56              : type :: htetra_bucket
      57              : 
      58              :   integer,allocatable :: indexes(:,:)
      59              : 
      60              : end type htetra_bucket
      61              : !!***
      62              : 
      63              : !!****t* m_htetra/htetra_t
      64              : !! NAME
      65              : !! htetra_t
      66              : !!
      67              : !! FUNCTION
      68              : !! tetrahedron geometry object
      69              : !!
      70              : !! SOURCE
      71              : 
      72              : type, public :: htetra_t
      73              : 
      74              :   integer :: opt
      75              :   ! Option for the generation of tetrahedra
      76              : 
      77              :   integer :: nkibz
      78              :   ! Number of points in the irreducible Brillouin zone
      79              : 
      80              :   integer :: nkbz
      81              :   ! Number of points in the full Brillouin zone
      82              : 
      83              :   integer :: nbuckets
      84              :   ! Number of buckets for the hash table
      85              : 
      86              :   integer :: nunique_tetra
      87              :   ! Number of unique tetrahedron
      88              : 
      89              :   integer :: nibz_tetra
      90              :   ! Number of ibz tetrahedron
      91              : 
      92              :   integer,allocatable :: tetra_total(:)
      93              :   ! (%nbkibz)
      94              :   ! Equivalent tetrahedra per kpoint (number of irred tetra times multiplicity)
      95              : 
      96              :   integer,allocatable :: tetra_count(:)
      97              :   ! (%nbkibz)
      98              :   ! Inequivalent tetrahedra per kpoint (number of irred tetra)
      99              : 
     100              :   integer,allocatable :: ibz_multiplicity(:)
     101              :   ! (%nbkibz)
     102              :   ! Multiplicity of each k-point
     103              : 
     104              :   real(dp)  :: vv
     105              :   ! volume of the tetrahedra
     106              : 
     107              :   real(dp) :: klatt(3, 3)
     108              :   ! reciprocal of equivalent supercell lattice vectors for full kpoint grid
     109              : 
     110              :   type(htetra_bucket),allocatable :: ibz(:)
     111              :   ! indexes of the tetrahedra for each k-point
     112              : 
     113              :   type(htetra_bucket),allocatable :: unique_tetra(:)
     114              :   ! indexes of the unique tetrahedra
     115              : 
     116              :   contains
     117              : 
     118              :   procedure :: init => htetra_init            ! Initialize the object
     119              : 
     120              :   procedure :: free  => htetra_free
     121              :     ! Free memory
     122              : 
     123              :   procedure :: print => htetra_print
     124              :     ! Print information about tetrahedron object
     125              : 
     126              :   procedure :: get_onewk => htetra_get_onewk
     127              :     ! Calculate integration weights and their derivatives for a single k-point in the IBZ.
     128              : 
     129              :   procedure ::  get_onewk_wvals => htetra_get_onewk_wvals
     130              :     ! Similar to tetra_get_onewk but receives arbitrary list of frequency points.
     131              : 
     132              :   procedure :: get_onewk_wvals_zinv => htetra_get_onewk_wvals_zinv
     133              :     ! Calculate integration weights for 1/(z-E(k)) for a single k-point in the IBZ.
     134              : 
     135              :   procedure :: weights_wvals_zinv => htetra_weights_wvals_zinv
     136              :     ! Same as above but return the weight on all the kpoints by looping over tetrahedra
     137              : 
     138              :   procedure :: wvals_weights => htetra_wvals_weights
     139              :     ! Compute delta and theta on a list of energies for all kpoints
     140              : 
     141              :   procedure :: wvals_weights_delta => htetra_wvals_weights_delta
     142              :     ! Compute delta on a list of energies for all kpoints
     143              : 
     144              :   procedure :: blochl_weights => htetra_blochl_weights
     145              :     ! And interface to help to facilitate the transition to the new tetrahedron implementation
     146              : 
     147              : end type htetra_t
     148              : !!***
     149              : 
     150              : !!***
     151              : 
     152              : contains
     153              : !!***
     154              : 
     155              : !----------------------------------------------------------------------
     156              : 
     157              : !!****f* m_htetra/htetra_init
     158              : !! NAME
     159              : !! htetra_init
     160              : !!
     161              : !! FUNCTION
     162              : !! get tetrahedra characterized by apexes
     163              : !!
     164              : !! INPUTS
     165              : !!  bz2ibz(nkpt_fullbz)=indexes of irred kpoints equivalent to kpt_fullbz
     166              : !!  gprimd(3,3) = reciprocal space vectors
     167              : !!  klatt(3,3)=reciprocal of lattice vectors for full kpoint grid
     168              : !!  kpt_fullbz(3,nkpt_fullbz)=kpoints in full brillouin zone
     169              : !!  nkpt_fullbz=number of kpoints in full brillouin zone
     170              : !!  options=1.generate 24 tetrahedra per k-point
     171              : !!            faster but gives different results depending on the IBZ, small error for large grids
     172              : !!          2.generate tetrahedra on the FBZ and map to IBZ
     173              : !!            slower but same results for IBZ and FBZ.
     174              : !!  comm= MPI communicator
     175              : !!  [opt]= 1 for Togo's version, 2 for Blochl's version (default)
     176              : !!
     177              : !! OUTPUT
     178              : !!  tetra%ibz(4,24,nkibz)=for each k-point, the indexes in the IBZ
     179              : !!  tetra%vv = tetrahedron volume divided by full BZ volume
     180              : !!
     181              : !! SOURCE
     182              : 
     183          486 : subroutine htetra_init(tetra, bz2ibz, gprimd, klatt, kpt_fullbz, nkpt_fullbz, kpt_ibz, nkpt_ibz, &
     184              :                        ierr, errorstring, comm, &
     185              :                        opt) ! optional
     186              : 
     187              : !Arguments ------------------------------------
     188              : !scalars
     189              :  class(htetra_t),intent(out),target :: tetra
     190              :  integer,intent(in) :: nkpt_fullbz, nkpt_ibz, comm
     191              :  integer,optional,intent(in) :: opt
     192              :  integer,intent(out) :: ierr
     193              :  character(len=80),intent(out) :: errorstring
     194              : !arrays
     195              :  integer,intent(in) :: bz2ibz(nkpt_fullbz)
     196              :  real(dp),intent(in) :: gprimd(3,3),klatt(3,3),kpt_fullbz(3,nkpt_fullbz),kpt_ibz(3,nkpt_ibz)
     197              : 
     198              : !Local variables-------------------------------
     199              : !scalars
     200              :  !type(octree_t) :: oct
     201          243 :  type(krank_t) :: krank
     202              :  integer :: ikpt2,isummit,itetra,jtetra
     203              :  integer :: ikibz,ikbz,idiag,ihash,min_idiag,my_rank,nprocs
     204              :  integer :: max_ntetra, ntetra
     205              :  real(dp) :: rcvol,length,min_length
     206              : !arrays
     207          243 :  integer,allocatable,target :: indexes(:,:), tetra_hash_count(:)
     208              :  integer :: tetra_ibz(4)
     209              :  integer :: tetra_shifts(3,4,24,4)  ! 3 dimensions, 4 summits, 24 tetrahedra, 4 main diagonals
     210              :  integer :: tetra_shifts_6(3,4,6,1) ! 3 dimensions, 4 summits, 6 tetrahedra, 4 main diagonals
     211              :  integer :: main_diagonals(3,4), tetra_mibz(0:4)
     212              :  real(dp)  :: k1(3),k2(3),k3(3),diag(3)
     213              : ! *********************************************************************
     214              : 
     215              :  ! Use the shifts from kpclib developed by Atsushi Togo
     216              :  ! This part is produced by a python script
     217              :  ! This implementation is based on spglib and kpclib by Atsushi Togo
     218              :  ! after a discussion with hin on the APS 2019 where he provided
     219              :  ! details of his implementation.
     220              :  ! Note that we don't use it in production as we found that is approach, although faster than the original
     221              :  ! one proposed by Blochl (and implemented by MJV) does not preserve symmetries that is calculations done on the full BZ
     222              :  ! and the IBZ do not produce the same result. The diff, however, decreases if the sampling is densified.
     223              : 
     224          972 :  tetra_shifts(:, 1, 1,1) = [  0,  0,  0]
     225          972 :  tetra_shifts(:, 2, 1,1) = [  1,  0,  0]
     226          972 :  tetra_shifts(:, 3, 1,1) = [  1,  1,  0]
     227          972 :  tetra_shifts(:, 4, 1,1) = [  1,  1,  1]
     228          972 :  tetra_shifts(:, 1, 2,1) = [  0,  0,  0]
     229          972 :  tetra_shifts(:, 2, 2,1) = [  1,  0,  0]
     230          972 :  tetra_shifts(:, 3, 2,1) = [  1,  0,  1]
     231          972 :  tetra_shifts(:, 4, 2,1) = [  1,  1,  1]
     232          972 :  tetra_shifts(:, 1, 3,1) = [  0,  0,  0]
     233          972 :  tetra_shifts(:, 2, 3,1) = [  0,  1,  0]
     234          972 :  tetra_shifts(:, 3, 3,1) = [  1,  1,  0]
     235          972 :  tetra_shifts(:, 4, 3,1) = [  1,  1,  1]
     236          972 :  tetra_shifts(:, 1, 4,1) = [  0,  0,  0]
     237          972 :  tetra_shifts(:, 2, 4,1) = [  0,  1,  0]
     238          972 :  tetra_shifts(:, 3, 4,1) = [  0,  1,  1]
     239          972 :  tetra_shifts(:, 4, 4,1) = [  1,  1,  1]
     240          972 :  tetra_shifts(:, 1, 5,1) = [  0,  0,  0]
     241          972 :  tetra_shifts(:, 2, 5,1) = [  0,  0,  1]
     242          972 :  tetra_shifts(:, 3, 5,1) = [  1,  0,  1]
     243          972 :  tetra_shifts(:, 4, 5,1) = [  1,  1,  1]
     244          972 :  tetra_shifts(:, 1, 6,1) = [  0,  0,  0]
     245          972 :  tetra_shifts(:, 2, 6,1) = [  0,  0,  1]
     246          972 :  tetra_shifts(:, 3, 6,1) = [  0,  1,  1]
     247          972 :  tetra_shifts(:, 4, 6,1) = [  1,  1,  1]
     248          972 :  tetra_shifts(:, 1, 7,1) = [  0,  0,  0]
     249          972 :  tetra_shifts(:, 2, 7,1) = [  0,  1,  0]
     250          972 :  tetra_shifts(:, 3, 7,1) = [  0,  1,  1]
     251          972 :  tetra_shifts(:, 4, 7,1) = [ -1,  0,  0]
     252          972 :  tetra_shifts(:, 1, 8,1) = [  0,  0,  0]
     253          972 :  tetra_shifts(:, 2, 8,1) = [  0,  0,  1]
     254          972 :  tetra_shifts(:, 3, 8,1) = [  0,  1,  1]
     255          972 :  tetra_shifts(:, 4, 8,1) = [ -1,  0,  0]
     256          972 :  tetra_shifts(:, 1, 9,1) = [  0,  0,  0]
     257          972 :  tetra_shifts(:, 2, 9,1) = [  1,  0,  0]
     258          972 :  tetra_shifts(:, 3, 9,1) = [  1,  0,  1]
     259          972 :  tetra_shifts(:, 4, 9,1) = [  0, -1,  0]
     260          972 :  tetra_shifts(:, 1,10,1) = [  0,  0,  0]
     261          972 :  tetra_shifts(:, 2,10,1) = [  0,  0,  1]
     262          972 :  tetra_shifts(:, 3,10,1) = [  1,  0,  1]
     263          972 :  tetra_shifts(:, 4,10,1) = [  0, -1,  0]
     264          972 :  tetra_shifts(:, 1,11,1) = [  0,  0,  0]
     265          972 :  tetra_shifts(:, 2,11,1) = [  0,  0,  1]
     266          972 :  tetra_shifts(:, 3,11,1) = [ -1, -1,  0]
     267          972 :  tetra_shifts(:, 4,11,1) = [  0, -1,  0]
     268          972 :  tetra_shifts(:, 1,12,1) = [  0,  0,  0]
     269          972 :  tetra_shifts(:, 2,12,1) = [  0,  0,  1]
     270          972 :  tetra_shifts(:, 3,12,1) = [ -1, -1,  0]
     271          972 :  tetra_shifts(:, 4,12,1) = [ -1,  0,  0]
     272          972 :  tetra_shifts(:, 1,13,1) = [  0,  0,  0]
     273          972 :  tetra_shifts(:, 2,13,1) = [  1,  0,  0]
     274          972 :  tetra_shifts(:, 3,13,1) = [  1,  1,  0]
     275          972 :  tetra_shifts(:, 4,13,1) = [  0,  0, -1]
     276          972 :  tetra_shifts(:, 1,14,1) = [  0,  0,  0]
     277          972 :  tetra_shifts(:, 2,14,1) = [  0,  1,  0]
     278          972 :  tetra_shifts(:, 3,14,1) = [  1,  1,  0]
     279          972 :  tetra_shifts(:, 4,14,1) = [  0,  0, -1]
     280          972 :  tetra_shifts(:, 1,15,1) = [  0,  0,  0]
     281          972 :  tetra_shifts(:, 2,15,1) = [  0,  1,  0]
     282          972 :  tetra_shifts(:, 3,15,1) = [ -1,  0, -1]
     283          972 :  tetra_shifts(:, 4,15,1) = [  0,  0, -1]
     284          972 :  tetra_shifts(:, 1,16,1) = [  0,  0,  0]
     285          972 :  tetra_shifts(:, 2,16,1) = [  0,  1,  0]
     286          972 :  tetra_shifts(:, 3,16,1) = [ -1,  0, -1]
     287          972 :  tetra_shifts(:, 4,16,1) = [ -1,  0,  0]
     288          972 :  tetra_shifts(:, 1,17,1) = [  0,  0,  0]
     289          972 :  tetra_shifts(:, 2,17,1) = [  1,  0,  0]
     290          972 :  tetra_shifts(:, 3,17,1) = [  0, -1, -1]
     291          972 :  tetra_shifts(:, 4,17,1) = [  0,  0, -1]
     292          972 :  tetra_shifts(:, 1,18,1) = [  0,  0,  0]
     293          972 :  tetra_shifts(:, 2,18,1) = [  1,  0,  0]
     294          972 :  tetra_shifts(:, 3,18,1) = [  0, -1, -1]
     295          972 :  tetra_shifts(:, 4,18,1) = [  0, -1,  0]
     296          972 :  tetra_shifts(:, 1,19,1) = [  0,  0,  0]
     297          972 :  tetra_shifts(:, 2,19,1) = [ -1, -1, -1]
     298          972 :  tetra_shifts(:, 3,19,1) = [  0, -1, -1]
     299          972 :  tetra_shifts(:, 4,19,1) = [  0,  0, -1]
     300          972 :  tetra_shifts(:, 1,20,1) = [  0,  0,  0]
     301          972 :  tetra_shifts(:, 2,20,1) = [ -1, -1, -1]
     302          972 :  tetra_shifts(:, 3,20,1) = [  0, -1, -1]
     303          972 :  tetra_shifts(:, 4,20,1) = [  0, -1,  0]
     304          972 :  tetra_shifts(:, 1,21,1) = [  0,  0,  0]
     305          972 :  tetra_shifts(:, 2,21,1) = [ -1, -1, -1]
     306          972 :  tetra_shifts(:, 3,21,1) = [ -1,  0, -1]
     307          972 :  tetra_shifts(:, 4,21,1) = [  0,  0, -1]
     308          972 :  tetra_shifts(:, 1,22,1) = [  0,  0,  0]
     309          972 :  tetra_shifts(:, 2,22,1) = [ -1, -1, -1]
     310          972 :  tetra_shifts(:, 3,22,1) = [ -1,  0, -1]
     311          972 :  tetra_shifts(:, 4,22,1) = [ -1,  0,  0]
     312          972 :  tetra_shifts(:, 1,23,1) = [  0,  0,  0]
     313          972 :  tetra_shifts(:, 2,23,1) = [ -1, -1, -1]
     314          972 :  tetra_shifts(:, 3,23,1) = [ -1, -1,  0]
     315          972 :  tetra_shifts(:, 4,23,1) = [  0, -1,  0]
     316          972 :  tetra_shifts(:, 1,24,1) = [  0,  0,  0]
     317          972 :  tetra_shifts(:, 2,24,1) = [ -1, -1, -1]
     318          972 :  tetra_shifts(:, 3,24,1) = [ -1, -1,  0]
     319          972 :  tetra_shifts(:, 4,24,1) = [ -1,  0,  0]
     320          972 :  tetra_shifts(:, 1, 1,2) = [  0,  0,  0]
     321          972 :  tetra_shifts(:, 2, 1,2) = [  1,  0,  0]
     322          972 :  tetra_shifts(:, 3, 1,2) = [  0,  1,  0]
     323          972 :  tetra_shifts(:, 4, 1,2) = [  0,  1,  1]
     324          972 :  tetra_shifts(:, 1, 2,2) = [  0,  0,  0]
     325          972 :  tetra_shifts(:, 2, 2,2) = [  1,  0,  0]
     326          972 :  tetra_shifts(:, 3, 2,2) = [  0,  0,  1]
     327          972 :  tetra_shifts(:, 4, 2,2) = [  0,  1,  1]
     328          972 :  tetra_shifts(:, 1, 3,2) = [  0,  0,  0]
     329          972 :  tetra_shifts(:, 2, 3,2) = [ -1,  1,  0]
     330          972 :  tetra_shifts(:, 3, 3,2) = [ -1,  1,  1]
     331          972 :  tetra_shifts(:, 4, 3,2) = [ -1,  0,  0]
     332          972 :  tetra_shifts(:, 1, 4,2) = [  0,  0,  0]
     333          972 :  tetra_shifts(:, 2, 4,2) = [ -1,  0,  1]
     334          972 :  tetra_shifts(:, 3, 4,2) = [ -1,  1,  1]
     335          972 :  tetra_shifts(:, 4, 4,2) = [ -1,  0,  0]
     336          972 :  tetra_shifts(:, 1, 5,2) = [  0,  0,  0]
     337          972 :  tetra_shifts(:, 2, 5,2) = [ -1,  1,  0]
     338          972 :  tetra_shifts(:, 3, 5,2) = [  0,  1,  0]
     339          972 :  tetra_shifts(:, 4, 5,2) = [ -1,  1,  1]
     340          972 :  tetra_shifts(:, 1, 6,2) = [  0,  0,  0]
     341          972 :  tetra_shifts(:, 2, 6,2) = [  0,  1,  0]
     342          972 :  tetra_shifts(:, 3, 6,2) = [ -1,  1,  1]
     343          972 :  tetra_shifts(:, 4, 6,2) = [  0,  1,  1]
     344          972 :  tetra_shifts(:, 1, 7,2) = [  0,  0,  0]
     345          972 :  tetra_shifts(:, 2, 7,2) = [ -1,  0,  1]
     346          972 :  tetra_shifts(:, 3, 7,2) = [  0,  0,  1]
     347          972 :  tetra_shifts(:, 4, 7,2) = [ -1,  1,  1]
     348          972 :  tetra_shifts(:, 1, 8,2) = [  0,  0,  0]
     349          972 :  tetra_shifts(:, 2, 8,2) = [  0,  0,  1]
     350          972 :  tetra_shifts(:, 3, 8,2) = [ -1,  1,  1]
     351          972 :  tetra_shifts(:, 4, 8,2) = [  0,  1,  1]
     352          972 :  tetra_shifts(:, 1, 9,2) = [  0,  0,  0]
     353          972 :  tetra_shifts(:, 2, 9,2) = [  0,  0,  1]
     354          972 :  tetra_shifts(:, 3, 9,2) = [  0, -1,  0]
     355          972 :  tetra_shifts(:, 4, 9,2) = [  1, -1,  0]
     356          972 :  tetra_shifts(:, 1,10,2) = [  0,  0,  0]
     357          972 :  tetra_shifts(:, 2,10,2) = [  1,  0,  0]
     358          972 :  tetra_shifts(:, 3,10,2) = [  0,  0,  1]
     359          972 :  tetra_shifts(:, 4,10,2) = [  1, -1,  0]
     360          972 :  tetra_shifts(:, 1,11,2) = [  0,  0,  0]
     361          972 :  tetra_shifts(:, 2,11,2) = [ -1,  0,  1]
     362          972 :  tetra_shifts(:, 3,11,2) = [  0, -1,  0]
     363          972 :  tetra_shifts(:, 4,11,2) = [ -1,  0,  0]
     364          972 :  tetra_shifts(:, 1,12,2) = [  0,  0,  0]
     365          972 :  tetra_shifts(:, 2,12,2) = [ -1,  0,  1]
     366          972 :  tetra_shifts(:, 3,12,2) = [  0,  0,  1]
     367          972 :  tetra_shifts(:, 4,12,2) = [  0, -1,  0]
     368          972 :  tetra_shifts(:, 1,13,2) = [  0,  0,  0]
     369          972 :  tetra_shifts(:, 2,13,2) = [  0,  1,  0]
     370          972 :  tetra_shifts(:, 3,13,2) = [  0,  0, -1]
     371          972 :  tetra_shifts(:, 4,13,2) = [  1,  0, -1]
     372          972 :  tetra_shifts(:, 1,14,2) = [  0,  0,  0]
     373          972 :  tetra_shifts(:, 2,14,2) = [  1,  0,  0]
     374          972 :  tetra_shifts(:, 3,14,2) = [  0,  1,  0]
     375          972 :  tetra_shifts(:, 4,14,2) = [  1,  0, -1]
     376          972 :  tetra_shifts(:, 1,15,2) = [  0,  0,  0]
     377          972 :  tetra_shifts(:, 2,15,2) = [ -1,  1,  0]
     378          972 :  tetra_shifts(:, 3,15,2) = [  0,  0, -1]
     379          972 :  tetra_shifts(:, 4,15,2) = [ -1,  0,  0]
     380          972 :  tetra_shifts(:, 1,16,2) = [  0,  0,  0]
     381          972 :  tetra_shifts(:, 2,16,2) = [ -1,  1,  0]
     382          972 :  tetra_shifts(:, 3,16,2) = [  0,  1,  0]
     383          972 :  tetra_shifts(:, 4,16,2) = [  0,  0, -1]
     384          972 :  tetra_shifts(:, 1,17,2) = [  0,  0,  0]
     385          972 :  tetra_shifts(:, 2,17,2) = [  0, -1, -1]
     386          972 :  tetra_shifts(:, 3,17,2) = [  1, -1, -1]
     387          972 :  tetra_shifts(:, 4,17,2) = [  0,  0, -1]
     388          972 :  tetra_shifts(:, 1,18,2) = [  0,  0,  0]
     389          972 :  tetra_shifts(:, 2,18,2) = [  0, -1, -1]
     390          972 :  tetra_shifts(:, 3,18,2) = [  1, -1, -1]
     391          972 :  tetra_shifts(:, 4,18,2) = [  0, -1,  0]
     392          972 :  tetra_shifts(:, 1,19,2) = [  0,  0,  0]
     393          972 :  tetra_shifts(:, 2,19,2) = [  1, -1, -1]
     394          972 :  tetra_shifts(:, 3,19,2) = [  0,  0, -1]
     395          972 :  tetra_shifts(:, 4,19,2) = [  1,  0, -1]
     396          972 :  tetra_shifts(:, 1,20,2) = [  0,  0,  0]
     397          972 :  tetra_shifts(:, 2,20,2) = [  1,  0,  0]
     398          972 :  tetra_shifts(:, 3,20,2) = [  1, -1, -1]
     399          972 :  tetra_shifts(:, 4,20,2) = [  1,  0, -1]
     400          972 :  tetra_shifts(:, 1,21,2) = [  0,  0,  0]
     401          972 :  tetra_shifts(:, 2,21,2) = [  1, -1, -1]
     402          972 :  tetra_shifts(:, 3,21,2) = [  0, -1,  0]
     403          972 :  tetra_shifts(:, 4,21,2) = [  1, -1,  0]
     404          972 :  tetra_shifts(:, 1,22,2) = [  0,  0,  0]
     405          972 :  tetra_shifts(:, 2,22,2) = [  1,  0,  0]
     406          972 :  tetra_shifts(:, 3,22,2) = [  1, -1, -1]
     407          972 :  tetra_shifts(:, 4,22,2) = [  1, -1,  0]
     408          972 :  tetra_shifts(:, 1,23,2) = [  0,  0,  0]
     409          972 :  tetra_shifts(:, 2,23,2) = [  0, -1, -1]
     410          972 :  tetra_shifts(:, 3,23,2) = [  0,  0, -1]
     411          972 :  tetra_shifts(:, 4,23,2) = [ -1,  0,  0]
     412          972 :  tetra_shifts(:, 1,24,2) = [  0,  0,  0]
     413          972 :  tetra_shifts(:, 2,24,2) = [  0, -1, -1]
     414          972 :  tetra_shifts(:, 3,24,2) = [  0, -1,  0]
     415          972 :  tetra_shifts(:, 4,24,2) = [ -1,  0,  0]
     416          972 :  tetra_shifts(:, 1, 1,3) = [  0,  0,  0]
     417          972 :  tetra_shifts(:, 2, 1,3) = [  1,  0,  0]
     418          972 :  tetra_shifts(:, 3, 1,3) = [  0,  1,  0]
     419          972 :  tetra_shifts(:, 4, 1,3) = [  1,  0,  1]
     420          972 :  tetra_shifts(:, 1, 2,3) = [  0,  0,  0]
     421          972 :  tetra_shifts(:, 2, 2,3) = [  0,  1,  0]
     422          972 :  tetra_shifts(:, 3, 2,3) = [  0,  0,  1]
     423          972 :  tetra_shifts(:, 4, 2,3) = [  1,  0,  1]
     424          972 :  tetra_shifts(:, 1, 3,3) = [  0,  0,  0]
     425          972 :  tetra_shifts(:, 2, 3,3) = [ -1,  1,  0]
     426          972 :  tetra_shifts(:, 3, 3,3) = [  0,  0,  1]
     427          972 :  tetra_shifts(:, 4, 3,3) = [ -1,  0,  0]
     428          972 :  tetra_shifts(:, 1, 4,3) = [  0,  0,  0]
     429          972 :  tetra_shifts(:, 2, 4,3) = [ -1,  1,  0]
     430          972 :  tetra_shifts(:, 3, 4,3) = [  0,  1,  0]
     431          972 :  tetra_shifts(:, 4, 4,3) = [  0,  0,  1]
     432          972 :  tetra_shifts(:, 1, 5,3) = [  0,  0,  0]
     433          972 :  tetra_shifts(:, 2, 5,3) = [  1, -1,  1]
     434          972 :  tetra_shifts(:, 3, 5,3) = [  0, -1,  0]
     435          972 :  tetra_shifts(:, 4, 5,3) = [  1, -1,  0]
     436          972 :  tetra_shifts(:, 1, 6,3) = [  0,  0,  0]
     437          972 :  tetra_shifts(:, 2, 6,3) = [  0, -1,  1]
     438          972 :  tetra_shifts(:, 3, 6,3) = [  1, -1,  1]
     439          972 :  tetra_shifts(:, 4, 6,3) = [  0, -1,  0]
     440          972 :  tetra_shifts(:, 1, 7,3) = [  0,  0,  0]
     441          972 :  tetra_shifts(:, 2, 7,3) = [  1,  0,  0]
     442          972 :  tetra_shifts(:, 3, 7,3) = [  1, -1,  1]
     443          972 :  tetra_shifts(:, 4, 7,3) = [  1, -1,  0]
     444          972 :  tetra_shifts(:, 1, 8,3) = [  0,  0,  0]
     445          972 :  tetra_shifts(:, 2, 8,3) = [  1,  0,  0]
     446          972 :  tetra_shifts(:, 3, 8,3) = [  1, -1,  1]
     447          972 :  tetra_shifts(:, 4, 8,3) = [  1,  0,  1]
     448          972 :  tetra_shifts(:, 1, 9,3) = [  0,  0,  0]
     449          972 :  tetra_shifts(:, 2, 9,3) = [  0, -1,  1]
     450          972 :  tetra_shifts(:, 3, 9,3) = [  1, -1,  1]
     451          972 :  tetra_shifts(:, 4, 9,3) = [  0,  0,  1]
     452          972 :  tetra_shifts(:, 1,10,3) = [  0,  0,  0]
     453          972 :  tetra_shifts(:, 2,10,3) = [  1, -1,  1]
     454          972 :  tetra_shifts(:, 3,10,3) = [  0,  0,  1]
     455          972 :  tetra_shifts(:, 4,10,3) = [  1,  0,  1]
     456          972 :  tetra_shifts(:, 1,11,3) = [  0,  0,  0]
     457          972 :  tetra_shifts(:, 2,11,3) = [  0, -1,  1]
     458          972 :  tetra_shifts(:, 3,11,3) = [  0, -1,  0]
     459          972 :  tetra_shifts(:, 4,11,3) = [ -1,  0,  0]
     460          972 :  tetra_shifts(:, 1,12,3) = [  0,  0,  0]
     461          972 :  tetra_shifts(:, 2,12,3) = [  0, -1,  1]
     462          972 :  tetra_shifts(:, 3,12,3) = [  0,  0,  1]
     463          972 :  tetra_shifts(:, 4,12,3) = [ -1,  0,  0]
     464          972 :  tetra_shifts(:, 1,13,3) = [  0,  0,  0]
     465          972 :  tetra_shifts(:, 2,13,3) = [  1,  0,  0]
     466          972 :  tetra_shifts(:, 3,13,3) = [  0,  0, -1]
     467          972 :  tetra_shifts(:, 4,13,3) = [  0,  1, -1]
     468          972 :  tetra_shifts(:, 1,14,3) = [  0,  0,  0]
     469          972 :  tetra_shifts(:, 2,14,3) = [  1,  0,  0]
     470          972 :  tetra_shifts(:, 3,14,3) = [  0,  1,  0]
     471          972 :  tetra_shifts(:, 4,14,3) = [  0,  1, -1]
     472          972 :  tetra_shifts(:, 1,15,3) = [  0,  0,  0]
     473          972 :  tetra_shifts(:, 2,15,3) = [ -1,  0, -1]
     474          972 :  tetra_shifts(:, 3,15,3) = [  0,  0, -1]
     475          972 :  tetra_shifts(:, 4,15,3) = [ -1,  1, -1]
     476          972 :  tetra_shifts(:, 1,16,3) = [  0,  0,  0]
     477          972 :  tetra_shifts(:, 2,16,3) = [ -1,  0, -1]
     478          972 :  tetra_shifts(:, 3,16,3) = [ -1,  1, -1]
     479          972 :  tetra_shifts(:, 4,16,3) = [ -1,  0,  0]
     480          972 :  tetra_shifts(:, 1,17,3) = [  0,  0,  0]
     481          972 :  tetra_shifts(:, 2,17,3) = [  0,  0, -1]
     482          972 :  tetra_shifts(:, 3,17,3) = [ -1,  1, -1]
     483          972 :  tetra_shifts(:, 4,17,3) = [  0,  1, -1]
     484          972 :  tetra_shifts(:, 1,18,3) = [  0,  0,  0]
     485          972 :  tetra_shifts(:, 2,18,3) = [  0,  1,  0]
     486          972 :  tetra_shifts(:, 3,18,3) = [ -1,  1, -1]
     487          972 :  tetra_shifts(:, 4,18,3) = [  0,  1, -1]
     488          972 :  tetra_shifts(:, 1,19,3) = [  0,  0,  0]
     489          972 :  tetra_shifts(:, 2,19,3) = [ -1,  1,  0]
     490          972 :  tetra_shifts(:, 3,19,3) = [ -1,  1, -1]
     491          972 :  tetra_shifts(:, 4,19,3) = [ -1,  0,  0]
     492          972 :  tetra_shifts(:, 1,20,3) = [  0,  0,  0]
     493          972 :  tetra_shifts(:, 2,20,3) = [ -1,  1,  0]
     494          972 :  tetra_shifts(:, 3,20,3) = [  0,  1,  0]
     495          972 :  tetra_shifts(:, 4,20,3) = [ -1,  1, -1]
     496          972 :  tetra_shifts(:, 1,21,3) = [  0,  0,  0]
     497          972 :  tetra_shifts(:, 2,21,3) = [  0,  0, -1]
     498          972 :  tetra_shifts(:, 3,21,3) = [  0, -1,  0]
     499          972 :  tetra_shifts(:, 4,21,3) = [  1, -1,  0]
     500          972 :  tetra_shifts(:, 1,22,3) = [  0,  0,  0]
     501          972 :  tetra_shifts(:, 2,22,3) = [  1,  0,  0]
     502          972 :  tetra_shifts(:, 3,22,3) = [  0,  0, -1]
     503          972 :  tetra_shifts(:, 4,22,3) = [  1, -1,  0]
     504          972 :  tetra_shifts(:, 1,23,3) = [  0,  0,  0]
     505          972 :  tetra_shifts(:, 2,23,3) = [ -1,  0, -1]
     506          972 :  tetra_shifts(:, 3,23,3) = [  0,  0, -1]
     507          972 :  tetra_shifts(:, 4,23,3) = [  0, -1,  0]
     508          972 :  tetra_shifts(:, 1,24,3) = [  0,  0,  0]
     509          972 :  tetra_shifts(:, 2,24,3) = [ -1,  0, -1]
     510          972 :  tetra_shifts(:, 3,24,3) = [  0, -1,  0]
     511          972 :  tetra_shifts(:, 4,24,3) = [ -1,  0,  0]
     512          972 :  tetra_shifts(:, 1, 1,4) = [  0,  0,  0]
     513          972 :  tetra_shifts(:, 2, 1,4) = [  1,  0,  0]
     514          972 :  tetra_shifts(:, 3, 1,4) = [  1,  1,  0]
     515          972 :  tetra_shifts(:, 4, 1,4) = [  0,  0,  1]
     516          972 :  tetra_shifts(:, 1, 2,4) = [  0,  0,  0]
     517          972 :  tetra_shifts(:, 2, 2,4) = [  0,  1,  0]
     518          972 :  tetra_shifts(:, 3, 2,4) = [  1,  1,  0]
     519          972 :  tetra_shifts(:, 4, 2,4) = [  0,  0,  1]
     520          972 :  tetra_shifts(:, 1, 3,4) = [  0,  0,  0]
     521          972 :  tetra_shifts(:, 2, 3,4) = [  0,  1,  0]
     522          972 :  tetra_shifts(:, 3, 3,4) = [ -1,  0,  1]
     523          972 :  tetra_shifts(:, 4, 3,4) = [ -1,  0,  0]
     524          972 :  tetra_shifts(:, 1, 4,4) = [  0,  0,  0]
     525          972 :  tetra_shifts(:, 2, 4,4) = [  0,  1,  0]
     526          972 :  tetra_shifts(:, 3, 4,4) = [ -1,  0,  1]
     527          972 :  tetra_shifts(:, 4, 4,4) = [  0,  0,  1]
     528          972 :  tetra_shifts(:, 1, 5,4) = [  0,  0,  0]
     529          972 :  tetra_shifts(:, 2, 5,4) = [  1,  0,  0]
     530          972 :  tetra_shifts(:, 3, 5,4) = [  0, -1,  1]
     531          972 :  tetra_shifts(:, 4, 5,4) = [  0, -1,  0]
     532          972 :  tetra_shifts(:, 1, 6,4) = [  0,  0,  0]
     533          972 :  tetra_shifts(:, 2, 6,4) = [  1,  0,  0]
     534          972 :  tetra_shifts(:, 3, 6,4) = [  0, -1,  1]
     535          972 :  tetra_shifts(:, 4, 6,4) = [  0,  0,  1]
     536          972 :  tetra_shifts(:, 1, 7,4) = [  0,  0,  0]
     537          972 :  tetra_shifts(:, 2, 7,4) = [ -1, -1,  1]
     538          972 :  tetra_shifts(:, 3, 7,4) = [ -1, -1,  0]
     539          972 :  tetra_shifts(:, 4, 7,4) = [  0, -1,  0]
     540          972 :  tetra_shifts(:, 1, 8,4) = [  0,  0,  0]
     541          972 :  tetra_shifts(:, 2, 8,4) = [ -1, -1,  1]
     542          972 :  tetra_shifts(:, 3, 8,4) = [ -1, -1,  0]
     543          972 :  tetra_shifts(:, 4, 8,4) = [ -1,  0,  0]
     544          972 :  tetra_shifts(:, 1, 9,4) = [  0,  0,  0]
     545          972 :  tetra_shifts(:, 2, 9,4) = [ -1, -1,  1]
     546          972 :  tetra_shifts(:, 3, 9,4) = [  0, -1,  1]
     547          972 :  tetra_shifts(:, 4, 9,4) = [  0, -1,  0]
     548          972 :  tetra_shifts(:, 1,10,4) = [  0,  0,  0]
     549          972 :  tetra_shifts(:, 2,10,4) = [ -1, -1,  1]
     550          972 :  tetra_shifts(:, 3,10,4) = [ -1,  0,  1]
     551          972 :  tetra_shifts(:, 4,10,4) = [ -1,  0,  0]
     552          972 :  tetra_shifts(:, 1,11,4) = [  0,  0,  0]
     553          972 :  tetra_shifts(:, 2,11,4) = [ -1, -1,  1]
     554          972 :  tetra_shifts(:, 3,11,4) = [  0, -1,  1]
     555          972 :  tetra_shifts(:, 4,11,4) = [  0,  0,  1]
     556          972 :  tetra_shifts(:, 1,12,4) = [  0,  0,  0]
     557          972 :  tetra_shifts(:, 2,12,4) = [ -1, -1,  1]
     558          972 :  tetra_shifts(:, 3,12,4) = [ -1,  0,  1]
     559          972 :  tetra_shifts(:, 4,12,4) = [  0,  0,  1]
     560          972 :  tetra_shifts(:, 1,13,4) = [  0,  0,  0]
     561          972 :  tetra_shifts(:, 2,13,4) = [  0,  0, -1]
     562          972 :  tetra_shifts(:, 3,13,4) = [  1,  0, -1]
     563          972 :  tetra_shifts(:, 4,13,4) = [  1,  1, -1]
     564          972 :  tetra_shifts(:, 1,14,4) = [  0,  0,  0]
     565          972 :  tetra_shifts(:, 2,14,4) = [  0,  0, -1]
     566          972 :  tetra_shifts(:, 3,14,4) = [  0,  1, -1]
     567          972 :  tetra_shifts(:, 4,14,4) = [  1,  1, -1]
     568          972 :  tetra_shifts(:, 1,15,4) = [  0,  0,  0]
     569          972 :  tetra_shifts(:, 2,15,4) = [  1,  0,  0]
     570          972 :  tetra_shifts(:, 3,15,4) = [  1,  0, -1]
     571          972 :  tetra_shifts(:, 4,15,4) = [  1,  1, -1]
     572          972 :  tetra_shifts(:, 1,16,4) = [  0,  0,  0]
     573          972 :  tetra_shifts(:, 2,16,4) = [  0,  1,  0]
     574          972 :  tetra_shifts(:, 3,16,4) = [  0,  1, -1]
     575          972 :  tetra_shifts(:, 4,16,4) = [  1,  1, -1]
     576          972 :  tetra_shifts(:, 1,17,4) = [  0,  0,  0]
     577          972 :  tetra_shifts(:, 2,17,4) = [  1,  0,  0]
     578          972 :  tetra_shifts(:, 3,17,4) = [  1,  1,  0]
     579          972 :  tetra_shifts(:, 4,17,4) = [  1,  1, -1]
     580          972 :  tetra_shifts(:, 1,18,4) = [  0,  0,  0]
     581          972 :  tetra_shifts(:, 2,18,4) = [  0,  1,  0]
     582          972 :  tetra_shifts(:, 3,18,4) = [  1,  1,  0]
     583          972 :  tetra_shifts(:, 4,18,4) = [  1,  1, -1]
     584          972 :  tetra_shifts(:, 1,19,4) = [  0,  0,  0]
     585          972 :  tetra_shifts(:, 2,19,4) = [  0,  0, -1]
     586          972 :  tetra_shifts(:, 3,19,4) = [  0,  1, -1]
     587          972 :  tetra_shifts(:, 4,19,4) = [ -1,  0,  0]
     588          972 :  tetra_shifts(:, 1,20,4) = [  0,  0,  0]
     589          972 :  tetra_shifts(:, 2,20,4) = [  0,  1,  0]
     590          972 :  tetra_shifts(:, 3,20,4) = [  0,  1, -1]
     591          972 :  tetra_shifts(:, 4,20,4) = [ -1,  0,  0]
     592          972 :  tetra_shifts(:, 1,21,4) = [  0,  0,  0]
     593          972 :  tetra_shifts(:, 2,21,4) = [  0,  0, -1]
     594          972 :  tetra_shifts(:, 3,21,4) = [  1,  0, -1]
     595          972 :  tetra_shifts(:, 4,21,4) = [  0, -1,  0]
     596          972 :  tetra_shifts(:, 1,22,4) = [  0,  0,  0]
     597          972 :  tetra_shifts(:, 2,22,4) = [  1,  0,  0]
     598          972 :  tetra_shifts(:, 3,22,4) = [  1,  0, -1]
     599          972 :  tetra_shifts(:, 4,22,4) = [  0, -1,  0]
     600          972 :  tetra_shifts(:, 1,23,4) = [  0,  0,  0]
     601          972 :  tetra_shifts(:, 2,23,4) = [  0,  0, -1]
     602          972 :  tetra_shifts(:, 3,23,4) = [ -1, -1,  0]
     603          972 :  tetra_shifts(:, 4,23,4) = [  0, -1,  0]
     604          972 :  tetra_shifts(:, 1,24,4) = [  0,  0,  0]
     605          972 :  tetra_shifts(:, 2,24,4) = [  0,  0, -1]
     606          972 :  tetra_shifts(:, 3,24,4) = [ -1, -1,  0]
     607          972 :  tetra_shifts(:, 4,24,4) = [ -1,  0,  0]
     608              : 
     609              :  ! These shifts are taken from previous tetrahedron implementation by MJV and BXU
     610              :  ! TODO: implement shifts for the other diagonals
     611          972 :  tetra_shifts_6(:,1,1,1) = [0,0,0]
     612          972 :  tetra_shifts_6(:,2,1,1) = [1,0,0]
     613          972 :  tetra_shifts_6(:,3,1,1) = [0,1,0]
     614          972 :  tetra_shifts_6(:,4,1,1) = [1,0,1]
     615          972 :  tetra_shifts_6(:,1,2,1) = [1,0,0]
     616          972 :  tetra_shifts_6(:,2,2,1) = [1,1,0]
     617          972 :  tetra_shifts_6(:,3,2,1) = [0,1,0]
     618          972 :  tetra_shifts_6(:,4,2,1) = [1,0,1]
     619          972 :  tetra_shifts_6(:,1,3,1) = [0,1,0]
     620          972 :  tetra_shifts_6(:,2,3,1) = [1,1,0]
     621          972 :  tetra_shifts_6(:,3,3,1) = [1,0,1]
     622          972 :  tetra_shifts_6(:,4,3,1) = [1,1,1]
     623          972 :  tetra_shifts_6(:,1,4,1) = [0,0,0]
     624          972 :  tetra_shifts_6(:,2,4,1) = [0,1,0]
     625          972 :  tetra_shifts_6(:,3,4,1) = [0,0,1]
     626          972 :  tetra_shifts_6(:,4,4,1) = [1,0,1]
     627          972 :  tetra_shifts_6(:,1,5,1) = [0,0,1]
     628          972 :  tetra_shifts_6(:,2,5,1) = [1,0,1]
     629          972 :  tetra_shifts_6(:,3,5,1) = [0,1,0]
     630          972 :  tetra_shifts_6(:,4,5,1) = [0,1,1]
     631          972 :  tetra_shifts_6(:,1,6,1) = [0,1,0]
     632          972 :  tetra_shifts_6(:,2,6,1) = [1,0,1]
     633          972 :  tetra_shifts_6(:,3,6,1) = [0,1,1]
     634          972 :  tetra_shifts_6(:,4,6,1) = [1,1,1]
     635              : 
     636          972 :  main_diagonals(:,1) = [ 1, 1, 1] ! 0-7
     637          972 :  main_diagonals(:,2) = [-1, 1, 1] ! 1-6
     638          972 :  main_diagonals(:,3) = [ 1,-1, 1] ! 2-5
     639          972 :  main_diagonals(:,4) = [ 1, 1,-1] ! 3-4
     640              : 
     641          243 :  nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
     642          243 :  tetra%nkibz = nkpt_ibz
     643          243 :  tetra%nkbz = nkpt_fullbz
     644              :  ! HM: this value should be important for performance
     645              :  ! more buckets means faster queries for unique tetrahedra
     646              :  ! but more memory due to the initial size TETRA_SIZE of the buckets
     647              :  ! when changing the number of buckets one should also change the hash function
     648              :  ! to distribute the tetrahedra in the buckets as uniformly as possible
     649              :  ! the simplest hash (not the best!) is:
     650              :  ! ihash = mod(sum(tetra_ibz),nbuckts)
     651              :  ! the value of sum(tetra_ibz) is between 1 and 4*nkibz so I use nkibz nbuckets
     652              :  ! a larger number of buckets should speed up finding the irreducible tetrahedra
     653              :  ! but with more memory allocated
     654          243 :  tetra%nbuckets = nkpt_ibz
     655          243 :  ierr = 0
     656       225265 :  ABI_CALLOC(tetra_hash_count,(tetra%nbuckets))
     657              : 
     658              :  ! Determine the smallest diagonal in k-space
     659              :  min_length = huge(min_length)
     660         1215 :  do idiag = 1,4
     661              :    diag(:) = gprimd(:,1)*main_diagonals(1,idiag)+&
     662              :              gprimd(:,2)*main_diagonals(2,idiag)+&
     663         3888 :              gprimd(:,3)*main_diagonals(3,idiag)
     664          972 :    length = sqrt(diag(1)*diag(1) + diag(2)*diag(2) + diag(3)*diag(3))
     665         1215 :    if (length < min_length) then
     666          246 :      min_length = length
     667          246 :      min_idiag = idiag
     668              :    end if
     669              :  end do
     670              : 
     671              :  ! HM TODO: Avoid krank and map the k-point grid to indexes
     672              :  ! Make full k-point rank arrays
     673              :  !oct = octree_init(kpt_fullbz,2**4,[-one,-one,-one],[two,two,two])
     674          243 :  call krank%init(nkpt_fullbz, kpt_fullbz)
     675              :  !
     676              :  ! HM (13/04/2019): I implement two different versions:
     677              :  ! 1. I only use 24 tetrahedra around the IBZ k-point
     678              :  ! following the approach of A. Togo (phonopy, spglib, kspclib).
     679              :  ! 2. I generate tetrahedra on the full Brillouin zone
     680              :  ! and keep track of how many are contributing to the IBZ point and the multiplicities,
     681              :  ! these can be more than 24 tetrahedra.
     682              :  ! This is equivalent to what Matthieu implemented but avoids large memory allocations.
     683              :  !
     684              :  ! The two implementations differ specially when using low k-point sampling
     685              :  ! (the second yields the same results using IBZ or FBZ, the first one not).
     686              :  ! For large sampling the two approaches yield similar results, with the first
     687              :  ! one using less memory, faster to generate and compute
     688              :  !
     689       225265 :  ABI_MALLOC(tetra%unique_tetra,(tetra%nbuckets))
     690       224779 :  do ihash=1,tetra%nbuckets
     691      8308075 :    ABI_CALLOC(tetra%unique_tetra(ihash)%indexes,(0:4,TETRA_SIZE))
     692              :  end do
     693          243 :  tetra%opt = 2; if (present(opt)) tetra%opt = opt
     694              : 
     695          243 :  select case(tetra%opt)
     696              :  case (1)
     697              :    ! For each k-point in the IBZ store 24 tetrahedra each referring to 4 k-points
     698            0 :    do ikibz=1,tetra%nkibz
     699              :      !if (mod(ikibz,nprocs) /= my_rank) cycle
     700            0 :      k1 = kpt_ibz(:,ikibz)
     701            0 :      tetra_loop1: do itetra=1,24
     702            0 :        do isummit=1,4
     703              :          ! Find the index of the neighbouring k-points in the BZ
     704              :          k2 = k1 + tetra_shifts(1,isummit,itetra,min_idiag)*klatt(:,1) + &
     705              :                    tetra_shifts(2,isummit,itetra,min_idiag)*klatt(:,2) + &
     706            0 :                    tetra_shifts(3,isummit,itetra,min_idiag)*klatt(:,3)
     707              :          ! Find full kpoint which is summit isummit of tetrahedron itetra around full kpt ikpt_full !
     708              :          !ikpt2 = octree_find(oct,k2,dist)
     709              :          !ikpt2 = octree_find_nearest_pbc(oct,k2,dist,shift)
     710              :          !if (dist>tol12) call exit(1)
     711            0 :          ikpt2 = krank%get_index(k2)
     712              :          ! Find the index of those points in the BZ and IBZ
     713            0 :          tetra_ibz(isummit) = bz2ibz(ikpt2)
     714              :        end do
     715              :        ! Sort index of irr k-point edges (need this so the comparison works)
     716            0 :        call sort_4tetra_int(tetra_ibz)
     717              : 
     718              :        ! Store only unique tetrahedra
     719              :        ! Compute a very simple hash for each tetrahedron
     720            0 :        ihash = compute_hash(tetra,tetra_ibz) !mod(sum(tetra_ibz),tetra%nbuckets)+1
     721              :        ! Loop over all tetrahedrons that contain this ikibz as first element
     722            0 :        do jtetra=1,tetra_hash_count(ihash)
     723              :          ! if tetrahedron already exists add multiplicity
     724            0 :          if (tetra%unique_tetra(ihash)%indexes(1,jtetra)/=tetra_ibz(1)) cycle
     725            0 :          if (tetra%unique_tetra(ihash)%indexes(2,jtetra)/=tetra_ibz(2)) cycle
     726            0 :          if (tetra%unique_tetra(ihash)%indexes(3,jtetra)/=tetra_ibz(3)) cycle
     727            0 :          if (tetra%unique_tetra(ihash)%indexes(4,jtetra)/=tetra_ibz(4)) cycle
     728            0 :          tetra%unique_tetra(ihash)%indexes(0,jtetra) = tetra%unique_tetra(ihash)%indexes(0,jtetra)+1
     729            0 :          cycle tetra_loop1
     730              :        end do
     731              :        ! Otherwise store new tetrahedron
     732            0 :        tetra_hash_count(ihash) = tetra_hash_count(ihash)+1
     733            0 :        max_ntetra = size(tetra%unique_tetra(ihash)%indexes,2)
     734              :        ! The contents don't fit the array so I have to resize it
     735            0 :        if (tetra_hash_count(ihash)>max_ntetra) then
     736            0 :          ABI_MALLOC(indexes,(0:4,max_ntetra+TETRA_STEP))
     737            0 :          indexes(0:4,:max_ntetra) = tetra%unique_tetra(ihash)%indexes
     738            0 :          indexes(:,max_ntetra+1:) = 0
     739            0 :          ABI_MOVE_ALLOC(indexes,tetra%unique_tetra(ihash)%indexes)
     740              :        end if
     741            0 :        tetra%unique_tetra(ihash)%indexes(1:,tetra_hash_count(ihash)) = tetra_ibz(:)
     742            0 :        tetra%unique_tetra(ihash)%indexes(0, tetra_hash_count(ihash)) = 1
     743              :      end do tetra_loop1
     744              :    end do
     745              :    ! HM: The multiplicity of the tetrahedrons computed so far is wrong because we are using IBZ
     746              :    ! I compute the k-point multiplicity so I can fix this later on
     747              :    ! Only needed in blochl_weights* interface for looping over tetrahedra.
     748              :    ! in the onewk routines the weight is known outside
     749            0 :    ABI_CALLOC(tetra%ibz_multiplicity,(tetra%nkibz))
     750            0 :    do ikbz=1,nkpt_fullbz
     751            0 :      ikibz = bz2ibz(ikbz)
     752            0 :      tetra%ibz_multiplicity(ikibz) = tetra%ibz_multiplicity(ikibz) + 1
     753              :    end do
     754              : 
     755              :  case(2)
     756          243 :    min_idiag = 1
     757              :    ! For each k-point in the BZ generate the 6 tetrahedra that tessellate a microzone
     758      1409584 :    do ikbz=1,tetra%nkbz
     759      5637364 :      k1 = kpt_fullbz(:,ikbz)
     760      9865630 :      tetra_loop2: do itetra=1,6
     761              :        ! Determine tetrahedron
     762     42280230 :        do isummit=1,4
     763              :          ! Find the index of the neighbouring k-points in the BZ
     764              :          k2 = k1 + tetra_shifts_6(1,isummit,itetra,min_idiag)*klatt(:,1) + &
     765              :                    tetra_shifts_6(2,isummit,itetra,min_idiag)*klatt(:,2) + &
     766    135296736 :                    tetra_shifts_6(3,isummit,itetra,min_idiag)*klatt(:,3)
     767              :          ! Find full kpoint which is summit isummit of tetrahedron itetra around full kpt ikpt_full !
     768              :          !ikpt2 = octree_find(oct,k2,dist)
     769              :          !ikpt2 = octree_find_nearest_pbc(oct,k2,dist,shift)
     770              :          !if (dist>tol12) call exit(1)
     771     33824184 :          ikpt2 = krank%get_index(k2)
     772              :          ! Find the index of those points in the BZ and IBZ
     773     42280230 :          tetra_ibz(isummit) = bz2ibz(ikpt2)
     774              :        end do
     775              :        ! Sort index of irr k-point edges (need this so the comparison works)
     776      8456046 :        call sort_4tetra_int(tetra_ibz)
     777              : 
     778              :        ! Store only unique tetrahedra
     779              :        ! Compute a very simple hash for each tetrahedron
     780      8456046 :        ihash = compute_hash(tetra,tetra_ibz) !mod(sum(tetra_ibz),tetra%nbuckets)+1
     781              :        ! Loop over all tetrahedrons that contain this ikibz as first element
     782    156269209 :        do jtetra=1,tetra_hash_count(ihash)
     783              :          ! if tetrahedron already exists add multiplicity
     784    151530110 :          if (tetra%unique_tetra(ihash)%indexes(1,jtetra)/=tetra_ibz(1)) cycle
     785      4805680 :          if (tetra%unique_tetra(ihash)%indexes(2,jtetra)/=tetra_ibz(2)) cycle
     786      3930585 :          if (tetra%unique_tetra(ihash)%indexes(3,jtetra)/=tetra_ibz(3)) cycle
     787      3716947 :          if (tetra%unique_tetra(ihash)%indexes(4,jtetra)/=tetra_ibz(4)) cycle
     788      3716947 :          tetra%unique_tetra(ihash)%indexes(0,jtetra) = tetra%unique_tetra(ihash)%indexes(0,jtetra)+1
     789    156269209 :          cycle tetra_loop2
     790              :        end do
     791              :        ! Otherwise store new tetrahedron
     792      4739099 :        tetra_hash_count(ihash) = tetra_hash_count(ihash)+1
     793      4739099 :        max_ntetra = size(tetra%unique_tetra(ihash)%indexes,2)
     794              :        ! The contents don't fit the array so I have to resize it
     795      4739099 :        if (tetra_hash_count(ihash)>max_ntetra) then
     796      1975152 :          ABI_MALLOC(indexes,(0:4,max_ntetra+TETRA_STEP))
     797     71822824 :          indexes(0:4,:max_ntetra) = tetra%unique_tetra(ihash)%indexes
     798     24360208 :          indexes(:,max_ntetra+1:) = 0
     799       658384 :          ABI_MOVE_ALLOC(indexes,tetra%unique_tetra(ihash)%indexes)
     800              :        end if
     801     23695495 :        tetra%unique_tetra(ihash)%indexes(1:,tetra_hash_count(ihash)) = tetra_ibz(:)
     802      6148440 :        tetra%unique_tetra(ihash)%indexes(0, tetra_hash_count(ihash)) = 1
     803              :      end do tetra_loop2
     804              :    end do
     805              :  case default
     806            0 :    ierr = 1
     807            0 :    write(errorstring,*) 'Invalid option for the generation of tetrahedra,',ch10,&
     808            0 :                         'possible options are:',ch10,&
     809            0 :                         '1. Generate 24 tetrahedra per k-point',ch10,&
     810            0 :                         '2. Generate tetrahedra in the FBZ a map to IBZ (default)'
     811          243 :    return
     812              :  end select
     813              : 
     814              :  !ierr = octree_free(oct)
     815          243 :  ABI_FREE(tetra_hash_count)
     816          243 :  call krank%free()
     817              : 
     818              :  ! Do some maintenance: free unused memory and count unique tetrahedra per IBZ point
     819          243 :  tetra%nunique_tetra = 0
     820       224779 :  do ihash=1,tetra%nbuckets
     821              :    ! Count tetrahedra in this bucket
     822      5522056 :    ntetra = count(tetra%unique_tetra(ihash)%indexes(0,:)>0)
     823       224536 :    tetra%nunique_tetra = tetra%nunique_tetra + ntetra
     824              :    ! Allocate array with right size
     825       673608 :    ABI_MALLOC(indexes,(0:4,ntetra))
     826     28883666 :    indexes = tetra%unique_tetra(ihash)%indexes(:,:ntetra)
     827       224779 :    ABI_MOVE_ALLOC(indexes, tetra%unique_tetra(ihash)%indexes)
     828              :  end do
     829              : 
     830              :  ! Sum the multiplicity
     831          729 :  ABI_MALLOC(tetra%tetra_count,(tetra%nkibz))
     832          729 :  ABI_MALLOC(tetra%tetra_total,(tetra%nkibz))
     833       224779 :  tetra%tetra_count = 0
     834       224779 :  tetra%tetra_total = 0
     835       224779 :  do ihash=1,tetra%nbuckets
     836       224536 :    ntetra = size(tetra%unique_tetra(ihash)%indexes,2)
     837      4963878 :    do itetra=1,ntetra
     838     28434594 :      tetra_mibz = tetra%unique_tetra(ihash)%indexes(:,itetra)
     839     23920031 :      do isummit=1,4
     840     18956396 :        ikibz = tetra_mibz(isummit)
     841     18956396 :        tetra%tetra_total(ikibz) = tetra%tetra_total(ikibz) + tetra_mibz(0)
     842     23695495 :        tetra%tetra_count(ikibz) = tetra%tetra_count(ikibz) + 1
     843              :      end do
     844              :    end do
     845              :  end do
     846       224779 :  tetra%nibz_tetra = sum(tetra%tetra_count)
     847              : 
     848              :  ! HM: This was being allocated here, however this is only used when we loop over kpoints
     849              :  ! I will only allocate this memory if the htetra_get_onewk_* routines are called (lazy evaluation)
     850              :  !call htetra_init_mapping_ibz(tetra)
     851              : 
     852              :  ! Calculate the volume of the tetrahedra
     853              :  rcvol = abs(gprimd(1,1)*(gprimd(2,2)*gprimd(3,3)-gprimd(3,2)*gprimd(2,3))- &
     854              :              gprimd(2,1)*(gprimd(1,2)*gprimd(3,3)-gprimd(3,2)*gprimd(1,3))+ &
     855          243 :              gprimd(3,1)*(gprimd(1,2)*gprimd(2,3)-gprimd(2,2)*gprimd(1,3)))
     856              : 
     857              :  ! Volume of all tetrahedra should be the same as that of tetra 1
     858              :  ! this is the volume of 1 tetrahedron, should be coherent with notation in Lehmann & Taut
     859          972 :  k1(:) = gprimd(:,1)*klatt(1,1) + gprimd(:,2)*klatt(2,1) + gprimd(:,3)*klatt(3,1)
     860          972 :  k2(:) = gprimd(:,1)*klatt(1,2) + gprimd(:,2)*klatt(2,2) + gprimd(:,3)*klatt(3,2)
     861          972 :  k3(:) = gprimd(:,1)*klatt(1,3) + gprimd(:,2)*klatt(2,3) + gprimd(:,3)*klatt(3,3)
     862              :  tetra%vv = abs(k1(1)*(k2(2)*k3(3)-k2(3)*k3(2))- &
     863              :                 k1(2)*(k2(1)*k3(3)-k2(3)*k3(1))+ &
     864          243 :                 k1(3)*(k2(1)*k3(2)-k2(2)*k3(1))) / 6.d0 / rcvol
     865              : 
     866              :  contains
     867      8456046 :  integer function compute_hash(tetra,t) result(ihash)
     868              :    class(htetra_t),intent(in) :: tetra
     869              :    integer,intent(in) :: t(4)
     870     42280230 :    ihash = mod(sum(t), tetra%nbuckets) + 1
     871              :    ! TODO: should use a more general hash function that supports more buckets
     872              :    ! Something like:
     873              :    ! id = t(1)*nk3+t(2)*nk2+t(3)*nk1+t(4)
     874              :    ! where nk is the number of points in the IBZ
     875              :    ! Computing this leads to overflow so should use
     876              :    ! mod computation operations
     877              :    ! (A + B) mod C = (A mod C + B mod C) mod C
     878              :    ! (A * B) mod C = (A mod C * B mod C) mod C
     879              :    ! A^B mod C = ( (A mod C)^B ) mod C
     880              :  end function compute_hash
     881              : 
     882              : end subroutine htetra_init
     883              : !!***
     884              : 
     885              : !----------------------------------------------------------------------
     886              : 
     887              : !!****f* m_htetra/htetra_init_mapping_ibz
     888              : !! NAME
     889              : !! htetra_init_mapping_ibz
     890              : !!
     891              : !! FUNCTION
     892              : !!  The mapping to the IBZ has its own allocation routine.
     893              : !!  I will only allocate this memory if the htetra_get_onewk_* routines are called (lazy evaluation)
     894              : !!
     895              : !! SOURCE
     896              : 
     897          157 : subroutine htetra_init_mapping_ibz(tetra)
     898              : 
     899              :  class(htetra_t),intent(inout) :: tetra
     900              : 
     901              :  integer :: ikibz, itetra, isummit, ihash, ntetra
     902          157 :  integer :: tetra_count(tetra%nkibz),tetra_mibz(0:4)
     903              :  real(dp) :: mem_mb
     904              : 
     905              :  ! Only execute the following if not yet allocated
     906          157 :  if (allocated(tetra%ibz)) return
     907              : 
     908              :  ! Allocate IBZ to tetrahedron mapping
     909        21562 :  ABI_MALLOC(tetra%ibz, (tetra%nkibz))
     910          314 :  mem_mb = ABI_MEM_MB(tetra%ibz)
     911        21248 :  do ikibz=1,tetra%nkibz
     912        63273 :    ABI_MALLOC(tetra%ibz(ikibz)%indexes, (2, tetra%tetra_count(ikibz)))
     913        21248 :    mem_mb = mem_mb + 2 * tetra%tetra_count(ikibz) * 4 * b2Mb
     914              :  end do
     915              : 
     916          157 :  call wrtout(std_out, sjoin(" Allocating tetra%ibz%indexes with memory:", ftoa(mem_mb, fmt="f8.1"), " [Mb] <<< MEM"))
     917              : 
     918              :  ! Create mapping from IBZ to unique tetrahedra
     919        21248 :  tetra_count = 0
     920        21248 :  do ihash=1,tetra%nbuckets
     921        21091 :    ntetra = size(tetra%unique_tetra(ihash)%indexes, dim=2)
     922       869866 :    do itetra=1,ntetra
     923      5091708 :      tetra_mibz = tetra%unique_tetra(ihash)%indexes(:,itetra)
     924      4264181 :      do isummit=1,4
     925      3394472 :        ikibz = tetra_mibz(isummit)
     926      3394472 :        tetra_count(ikibz) = tetra_count(ikibz) + 1
     927      3394472 :        tetra%ibz(ikibz)%indexes(1, tetra_count(ikibz)) = ihash
     928      4243090 :        tetra%ibz(ikibz)%indexes(2, tetra_count(ikibz)) = itetra
     929              :      end do
     930              :    end do
     931              :  end do
     932              : 
     933              : end subroutine htetra_init_mapping_ibz
     934              : !!***
     935              : 
     936              : !----------------------------------------------------------------------
     937              : 
     938              : !!****f* m_htetra/htetra_get_ibz
     939              : !! NAME
     940              : !! htetra_get_ibz
     941              : !!
     942              : !! FUNCTION
     943              : !!  Get the itetra tetrahedron contributing to the ikibz k-point
     944              : !!
     945              : !! SOURCE
     946              : 
     947     15710160 : pure subroutine htetra_get_ibz(tetra, ikibz, itetra, tetra_mibz)
     948              : 
     949              :  class(htetra_t), intent(in) :: tetra
     950              :  integer,intent(in) :: ikibz, itetra
     951              :  integer,intent(out) :: tetra_mibz(0:4)
     952              :  integer :: ihash, jtetra
     953              : 
     954     15710160 :  ihash  = tetra%ibz(ikibz)%indexes(1,itetra)
     955     15710160 :  jtetra = tetra%ibz(ikibz)%indexes(2,itetra)
     956     94260960 :  tetra_mibz = tetra%unique_tetra(ihash)%indexes(:,jtetra)
     957              : 
     958     15710160 : end subroutine htetra_get_ibz
     959              : !!***
     960              : 
     961              : !----------------------------------------------------------------------
     962              : 
     963              : !!****f* m_htetra/htetra_print
     964              : !! NAME
     965              : !! htetra_print
     966              : !!
     967              : !! FUNCTION
     968              : !!  write information about the tetrahedra object
     969              : !!
     970              : !! SOURCE
     971              : 
     972           62 : subroutine htetra_print(self, unit)
     973              : 
     974              :  class(htetra_t), intent(in) :: self
     975              :  integer,intent(in) :: unit
     976              : 
     977              :  real(dp) :: total_size, unique_tetra_size, ibz_pointer_size
     978              : 
     979           62 :  if (unit == dev_null) return
     980              : 
     981           62 :  unique_tetra_size = self%nunique_tetra * 5* four / 1024 ** 2
     982           62 :  total_size        = unique_tetra_size
     983              :  !write(unit,'(a,i0)')     ' htetra unique_tetra:', self%nunique_tetra
     984              :  !write(unit,'(a,f12.1,a)') ' htetra unique_tetra_size ', unique_tetra_size, ' [Mb] <<< MEM'
     985           62 :  if (allocated(self%ibz)) then
     986            0 :    ibz_pointer_size  = self%nibz_tetra*2*four / 1024 ** 2
     987            0 :    write(unit,'(a,i0)')     ' ibz_tetra: ', self%nibz_tetra
     988            0 :    write(unit,'(a,f12.1,a)') ' ibz_tetra_size: ', ibz_pointer_size, ' [Mb] <<< MEM'
     989            0 :    total_size = total_size + ibz_pointer_size
     990              :  end if
     991              :  ! integer arrays
     992           62 :  total_size = total_size + 3 * (self%nkibz * 4) / 1024**2
     993           62 :  write(unit,'(a,f12.1,a)') ' htetra total size:', total_size, ' [Mb] <<< MEM'
     994              : 
     995              : end subroutine htetra_print
     996              : !!***
     997              : 
     998              : !----------------------------------------------------------------------
     999              : 
    1000              : !!****f* m_htetra/htetra_free
    1001              : !! NAME
    1002              : !! htetra_free
    1003              : !!
    1004              : !! FUNCTION
    1005              : !! deallocate tetrahedra pointers if needed
    1006              : !!
    1007              : !! SOURCE
    1008              : 
    1009          374 : subroutine htetra_free(tetra)
    1010              : 
    1011              :  class(htetra_t), intent(inout) :: tetra
    1012              :  integer :: ikibz,ihash
    1013              : 
    1014          374 :  ABI_SFREE(tetra%tetra_count)
    1015          374 :  ABI_SFREE(tetra%tetra_total)
    1016          374 :  ABI_SFREE(tetra%ibz_multiplicity)
    1017              : 
    1018          374 :  if (allocated(tetra%unique_tetra)) then
    1019       224779 :    do ihash=1,tetra%nbuckets
    1020       224779 :      ABI_SFREE(tetra%unique_tetra(ihash)%indexes)
    1021              :    end do
    1022       224779 :    ABI_FREE(tetra%unique_tetra)
    1023              :  end if
    1024              : 
    1025          374 :  if (allocated(tetra%ibz)) then
    1026        21248 :    do ikibz=1,tetra%nkibz
    1027        21248 :      ABI_SFREE(tetra%ibz(ikibz)%indexes)
    1028              :    end do
    1029        21248 :    ABI_FREE(tetra%ibz)
    1030              :  end if
    1031              : 
    1032          374 : end subroutine htetra_free
    1033              : !!***
    1034              : 
    1035              : !----------------------------------------------------------------------
    1036              : 
    1037              : !!****f* m_htetra/get_onetetra_blochl
    1038              : !! NAME
    1039              : !! get_onetetra_blochl
    1040              : !!
    1041              : !! FUNCTION
    1042              : !! Private function to calculate the contributions to the weights due to a single tetrahedron.
    1043              : !! Extracted from get_tetra_weight
    1044              : !!
    1045              : !! SOURCE
    1046              : 
    1047    138582926 : pure subroutine get_onetetra_blochl(eig, energies, nene, bcorr, tweight, dweight)
    1048              : 
    1049              : !Arguments ------------------------------------
    1050              : !scalars
    1051              :  integer,intent(in)   :: nene,bcorr
    1052              : !arrays
    1053              :  real(dp),intent(in)  :: eig(4), energies(nene)
    1054              :  real(dp), intent(out) :: tweight(4, nene), dweight(4, nene)
    1055              : 
    1056              : !Local variables-------------------------------
    1057              :  integer :: ieps
    1058              :  real(dp) :: cc,cc1,cc2,cc3
    1059              :  real(dp) :: dcc1de,dcc2de,dcc3de,dccde,eps
    1060              :  real(dp) :: e21,e31,e32,e41,e42,e43
    1061              :  real(dp) :: inv_e32,inv_e41,inv_e42,inv_e43,inv_e21,inv_e31
    1062              :  real(dp) :: deleps1,deleps2,deleps3,deleps4
    1063              :  real(dp) :: e1,e2,e3,e4
    1064              :  real(dp) :: invepsum, cc_pre, dccde_pre
    1065              :  real(dp) :: cc1_pre, cc2_pre, cc3_pre
    1066              :  real(dp) :: dccde_tmp
    1067              :  real(dp) :: bcorr_fact
    1068              : ! *********************************************************************
    1069              : 
    1070              :  ! This is output
    1071  >13491*10^7 :  tweight = zero; dweight = zero
    1072              : 
    1073              :  ! all notations are from Blochl PRB 49 16223 [[cite:Bloechl1994a]] Appendix B
    1074    138582926 :  e1 = eig(1)
    1075    138582926 :  e2 = eig(2)
    1076    138582926 :  e3 = eig(3)
    1077    138582926 :  e4 = eig(4)
    1078    138582926 :  e21 = e2-e1
    1079    138582926 :  e31 = e3-e1
    1080    138582926 :  e41 = e4-e1
    1081    138582926 :  e32 = e3-e2
    1082    138582926 :  e42 = e4-e2
    1083    138582926 :  e43 = e4-e3
    1084    138582926 :  inv_e21 = zero; if (e21 > tol14) inv_e21 = 1.d0 / e21
    1085    138582926 :  inv_e31 = zero; if (e31 > tol14) inv_e31 = 1.d0 / e31
    1086    138582926 :  inv_e41 = zero; if (e41 > tol14) inv_e41 = 1.d0 / e41
    1087    138582926 :  inv_e32 = zero; if (e32 > tol14) inv_e32 = 1.d0 / e32
    1088    138582926 :  inv_e42 = zero; if (e42 > tol14) inv_e42 = 1.d0 / e42
    1089    138582926 :  inv_e43 = zero; if (e43 > tol14) inv_e43 = 1.d0 / e43
    1090              : 
    1091   7878293144 :  do ieps=1,nene
    1092   7770985705 :    eps = energies(ieps)
    1093              : 
    1094              :    !
    1095              :    ! eps < e1 nothing to do
    1096              :    !
    1097   7770985705 :    if (eps < e1) cycle
    1098              : 
    1099              :    !
    1100              :    ! e1 < eps < e2
    1101              :    !
    1102    510470751 :    if (eps < e2) then
    1103    172325526 :      deleps1 = eps-e1
    1104    172325526 :      invepsum = inv_e21+inv_e31+inv_e41
    1105              : 
    1106              :      ! Heaviside
    1107    172325526 :      cc = inv_e21*inv_e31*inv_e41*deleps1**3
    1108    172325526 :      tweight(1,ieps) = cc*(4.d0-deleps1*invepsum)
    1109    172325526 :      tweight(2,ieps) = cc*deleps1*inv_e21
    1110    172325526 :      tweight(3,ieps) = cc*deleps1*inv_e31
    1111    172325526 :      tweight(4,ieps) = cc*deleps1*inv_e41
    1112              : 
    1113              :      ! Delta
    1114    172325526 :      dccde_pre = 3.d0*inv_e21*inv_e31*inv_e41
    1115    172325526 :      dccde = dccde_pre*deleps1**2
    1116    172325526 :      dweight(1,ieps) = dccde*(4.d0-deleps1*invepsum)-cc*invepsum
    1117    172325526 :      dweight(2,ieps) = (dccde*deleps1+cc) * inv_e21
    1118    172325526 :      dweight(3,ieps) = (dccde*deleps1+cc) * inv_e31
    1119    172325526 :      dweight(4,ieps) = (dccde*deleps1+cc) * inv_e41
    1120              : 
    1121    172325526 :      if (bcorr == 1) then
    1122              :        ! bxu, correction terms based on Bloechl's paper
    1123            0 :        bcorr_fact = 4.d0/40.d0*dccde_pre*deleps1*deleps1
    1124            0 :        tweight(1,ieps) = tweight(1,ieps) + bcorr_fact*( e21+e31+e41)
    1125            0 :        tweight(2,ieps) = tweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
    1126            0 :        tweight(3,ieps) = tweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
    1127            0 :        tweight(4,ieps) = tweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
    1128              : 
    1129            0 :        bcorr_fact = 8.d0/40.d0*dccde_pre*deleps1
    1130            0 :        dweight(1,ieps) = dweight(1,ieps) + bcorr_fact*( e21+e31+e41)
    1131            0 :        dweight(2,ieps) = dweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
    1132            0 :        dweight(3,ieps) = dweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
    1133            0 :        dweight(4,ieps) = dweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
    1134              :      end if
    1135              : 
    1136              :      cycle
    1137              :    endif
    1138              : 
    1139              :    !
    1140              :    ! e2 < eps < e3
    1141              :    !
    1142    338145225 :    if (eps < e3) then
    1143    144551565 :      deleps1 = eps-e1
    1144    144551565 :      deleps2 = eps-e2
    1145    144551565 :      deleps3 = e3-eps
    1146    144551565 :      deleps4 = e4-eps
    1147    144551565 :      cc1_pre = inv_e31*inv_e41
    1148    144551565 :      cc2_pre = inv_e41*inv_e32*inv_e31
    1149    144551565 :      cc3_pre = inv_e42*inv_e32*inv_e41
    1150              : 
    1151              :      ! Heaviside
    1152    144551565 :      cc1 = cc1_pre*deleps1*deleps1
    1153    144551565 :      cc2 = cc2_pre*deleps1*deleps2*deleps3
    1154    144551565 :      cc3 = cc3_pre*deleps2*deleps2*deleps4
    1155              : 
    1156              :      tweight(1,ieps) = (cc1)+&
    1157              :                        (cc1+cc2)*deleps3*inv_e31+&
    1158    144551565 :                        (cc1+cc2+cc3)*deleps4*inv_e41
    1159              :      tweight(2,ieps) = (cc1+cc2+cc3)+&
    1160              :                        (cc2+cc3)*deleps3*inv_e32+&
    1161    144551565 :                            (cc3)*deleps4*inv_e42
    1162              :      tweight(3,ieps) = (cc1+cc2)*deleps1*inv_e31+&
    1163    144551565 :                        (cc2+cc3)*deleps2*inv_e32
    1164              :      tweight(4,ieps) = (cc1+cc2+cc3)*deleps1*inv_e41+&
    1165    144551565 :                                    (cc3)*deleps2*inv_e42
    1166              : 
    1167              :      ! Delta
    1168    144551565 :      dcc1de = cc1_pre*(2.d0*deleps1)
    1169    144551565 :      dcc2de = cc2_pre*(    -deleps1*deleps2+deleps1*deleps3+deleps2*deleps3)
    1170    144551565 :      dcc3de = cc3_pre*(2.d0*deleps2*deleps4-deleps2*deleps2)
    1171              :      dweight(1,ieps) = dcc1de+&
    1172              :                        ((dcc1de+dcc2de)*deleps3-(cc1+cc2))*inv_e31+&
    1173    144551565 :                        ((dcc1de+dcc2de+dcc3de)*deleps4-(cc1+cc2+cc3))*inv_e41
    1174              :      dweight(2,ieps) = (dcc1de+dcc2de+dcc3de)+&
    1175              :                        ((dcc2de+dcc3de)*deleps3-(cc2+cc3))*inv_e32+&
    1176    144551565 :                                       (dcc3de*deleps4-cc3)*inv_e42
    1177              :      dweight(3,ieps) = ((dcc1de+dcc2de)*deleps1+(cc1+cc2))*inv_e31+&
    1178    144551565 :                        ((dcc2de+dcc3de)*deleps2+(cc2+cc3))*inv_e32
    1179              :      dweight(4,ieps) = ((dcc1de+dcc2de+dcc3de)*deleps1+(cc1+cc2+cc3))*inv_e41+&
    1180    144551565 :                                                         (dcc3de*deleps2+cc3)*inv_e42
    1181              : 
    1182    144551565 :      if (bcorr == 1) then
    1183              :        ! bxu, correction terms based on Bloechl's paper
    1184              :        ! The correction terms may cause the dweight become negative
    1185            0 :        bcorr_fact = 4.d0/40.d0*cc1_pre*(3.d0*e21+6.d0*deleps2-3.d0*(e31+e42)*deleps2*deleps2*inv_e32*inv_e42)
    1186            0 :        tweight(1,ieps) = tweight(1,ieps) + bcorr_fact*( e21+e31+e41)
    1187            0 :        tweight(2,ieps) = tweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
    1188            0 :        tweight(3,ieps) = tweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
    1189            0 :        tweight(4,ieps) = tweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
    1190              : 
    1191            0 :        bcorr_fact = 4.d0/40.d0*cc1_pre*(6.d0-6.d0*(e31+e42)*deleps2*inv_e32*inv_e42)
    1192            0 :        dweight(1,ieps) = dweight(1,ieps) + bcorr_fact*( e21+e31+e41)
    1193            0 :        dweight(2,ieps) = dweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
    1194            0 :        dweight(3,ieps) = dweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
    1195            0 :        dweight(4,ieps) = dweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
    1196              :      end if
    1197              : 
    1198              :      cycle
    1199              :    endif
    1200              : 
    1201              :    !
    1202              :    ! e3 < eps < e4
    1203              :    !
    1204    193593660 :    if (eps < e4) then
    1205    162310083 :      deleps4 = e4-eps
    1206    162310083 :      invepsum = inv_e41+inv_e42+inv_e43
    1207              : 
    1208              :      ! Heaviside
    1209    162310083 :      cc_pre = inv_e41*inv_e42*inv_e43
    1210    162310083 :      cc = cc_pre*deleps4**3
    1211    162310083 :      tweight(1,ieps) = one - deleps4*cc*inv_e41
    1212    162310083 :      tweight(2,ieps) = one - deleps4*cc*inv_e42
    1213    162310083 :      tweight(3,ieps) = one - deleps4*cc*inv_e43
    1214    162310083 :      tweight(4,ieps) = one - cc*(4.d0-deleps4*invepsum)
    1215              : 
    1216              :      ! Delta
    1217    162310083 :      dccde = -3.d0*cc_pre*deleps4**2
    1218    162310083 :      dccde_tmp = dccde*deleps4 - cc
    1219    162310083 :      dweight(1,ieps) = -dccde_tmp * inv_e41
    1220    162310083 :      dweight(2,ieps) = -dccde_tmp * inv_e42
    1221    162310083 :      dweight(3,ieps) = -dccde_tmp * inv_e43
    1222    162310083 :      dweight(4,ieps) = -4.d0*dccde + dccde_tmp*invepsum
    1223              : 
    1224    162310083 :      if (bcorr == 1) then
    1225              :        ! bxu, correction terms based on Bloechl's paper
    1226              :        ! The correction terms may cause the dweight become negative
    1227            0 :        bcorr_fact = 12.d0/40.d0*cc_pre*deleps4*deleps4
    1228            0 :        tweight(1,ieps) = tweight(1,ieps) + bcorr_fact*( e21+e31+e41)
    1229            0 :        tweight(2,ieps) = tweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
    1230            0 :        tweight(3,ieps) = tweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
    1231            0 :        tweight(4,ieps) = tweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
    1232              : 
    1233            0 :        bcorr_fact = - 24.d0/40.d0*cc_pre*deleps4
    1234            0 :        dweight(1,ieps) = dweight(1,ieps) + bcorr_fact*( e21+e31+e41)
    1235            0 :        dweight(2,ieps) = dweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
    1236            0 :        dweight(3,ieps) = dweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
    1237            0 :        dweight(4,ieps) = dweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
    1238              :      end if
    1239              : 
    1240              :      cycle
    1241              :    endif
    1242              : 
    1243              :    !
    1244              :    ! e4 < eps
    1245              :    !
    1246    138591016 :    if (e4 < eps) then
    1247              : 
    1248              :      ! Heaviside
    1249  28719032867 :      tweight(:,ieps:) = one
    1250              : 
    1251              :      ! Delta unchanged by this tetrahedron
    1252              :      exit
    1253              :    end if
    1254              : 
    1255              :    !  if we have a fully degenerate tetrahedron,
    1256              :    !  1) the tweight is a Heaviside (step) function, which is correct above, but
    1257              :    !  2) the dweight should contain a Dirac function
    1258              :    !
    1259              :  end do
    1260              : 
    1261    138582926 : end subroutine get_onetetra_blochl
    1262              : !!***
    1263              : 
    1264              : !!****f* m_htetra/get_onetetra_lambinvigneron
    1265              : !! NAME
    1266              : !! get_onetetra_lambinvigneron
    1267              : !!
    1268              : !! FUNCTION
    1269              : !!  Compute the complex weights according to: P. Lambin and J.P. Vigneron, Phys. Rev. B 29, 3430 (1984)
    1270              : !!  This routine is adapted from tdep where it was implemented
    1271              : !!  by Olle Hellman, all credits go to him
    1272              : !!
    1273              : !! INPUTS
    1274              : !!
    1275              : !! OUTPUT
    1276              : !!
    1277              : !! SOURCE
    1278              : 
    1279              : !pure
    1280            0 : subroutine get_onetetra_lambinvigneron(eig, z, cw)
    1281              : 
    1282              :     ! dispersion values at the corners of the tetrahedron
    1283              :     real(dp), intent(in) :: eig(4)
    1284              :     ! energy to evaluate the weights at
    1285              :     complex(dp), intent(in) :: z
    1286              :     ! complex weights
    1287              :     complex(dp), intent(out) :: cw(4)
    1288              :     complex(dp) :: EZ1,EZ2,EZ3,EZ4
    1289              :     real(dp) :: tol = tol14
    1290              :     !real(dp) :: tol = tol10
    1291              :     !real(dp) :: tol = tol6
    1292              :     real(dp) :: Emin,Emax,Zdist
    1293              :     real(dp) :: E12,E13,E14,E23,E24,E34
    1294              :     real(dp) :: a,b,c,d,e,f
    1295              :     complex(dp) zmE(4), verli(4) !, verm(4)
    1296              :     !integer :: ii, jj
    1297              : 
    1298            0 :     cw = zero
    1299              : 
    1300              :     ! Min and max energy
    1301            0 :     Emin=eig(1)
    1302            0 :     Emax=eig(4)
    1303              : 
    1304              :     ! First the complex energy differences
    1305            0 :     zmE = z - eig(:)
    1306            0 :     EZ1=z-eig(1)
    1307            0 :     EZ2=z-eig(2)
    1308            0 :     EZ3=z-eig(3)
    1309            0 :     EZ4=z-eig(4)
    1310              :     ! Smallest distance |z-Ei|, to determine whether I should switch to the
    1311              :     ! asymptotic behavior for numerical stability.
    1312              :     Zdist=huge(Zdist)
    1313              :     Zdist=min(Zdist,abs(EZ2))
    1314              :     Zdist=min(Zdist,abs(EZ3))
    1315              :     Zdist=min(Zdist,abs(EZ4))
    1316              :     !@TODO add asymptotic thing with continued fractions
    1317              : 
    1318              :     ! Then the energy differences, for the coefficients. Must always be positive, I hope.
    1319            0 :     E12=eig(2)-eig(1)
    1320            0 :     E13=eig(3)-eig(1)
    1321            0 :     E14=eig(4)-eig(1)
    1322            0 :     E23=eig(3)-eig(2)
    1323            0 :     E24=eig(4)-eig(2)
    1324            0 :     E34=eig(4)-eig(3)
    1325            0 :     a=zero; if ( E12 .gt. tol ) a=one/E12
    1326            0 :     b=zero; if ( E13 .gt. tol ) b=one/E13
    1327            0 :     c=zero; if ( E14 .gt. tol ) c=one/E14
    1328            0 :     d=zero; if ( E23 .gt. tol ) d=one/E23
    1329            0 :     e=zero; if ( E24 .gt. tol ) e=one/E24
    1330            0 :     f=zero; if ( E34 .gt. tol ) f=one/E34
    1331              : 
    1332              :     ! Now get the actual weights
    1333              :     ! e1=e2=e3=e4
    1334            0 :     if ( E12+E23+E34 .lt. tol ) then
    1335              : #if 0
    1336              :         !print *, "e1=e2=e3=e4"
    1337              :         cw(1)=0.25_dp/EZ1
    1338              :         cw(2)=0.25_dp/EZ2
    1339              :         cw(3)=0.25_dp/EZ3
    1340              :         cw(4)=0.25_dp/EZ4
    1341              : #else
    1342            0 :         call SIM0TWOI(cw, VERLI, z-eig)
    1343              : #endif
    1344              :     !    e2=e3=e4  ! diff wrt simteta
    1345            0 :     elseif ( E23+E34 .lt. tol ) then
    1346              : #if 0
    1347              :         !print *, "e2=e3=e4"
    1348              :         cw(1)=-a - (3*a**2*EZ2)*half + 3*a**3*EZ1*EZ2 + 3*a**4*EZ1**2*EZ2*Log(EZ2/EZ1)
    1349              :         cw(2)=-a - (3*a**2*EZ2)*half + 3*a**3*EZ1*EZ2 + 3*a**4*EZ1**2*EZ2*Log(EZ2/EZ1)
    1350              :         cw(3)=-a - (3*a**2*EZ2)*half + 3*a**3*EZ1*EZ2 + 3*a**4*EZ1**2*EZ2*Log(EZ2/EZ1)
    1351              :         cw(4)=-a*third + (a**2*EZ1)*half - a**3*EZ1**2 + a**4*EZ1**3*Log(EZ2/EZ1)
    1352              : #else
    1353            0 :         call SIM0TWOI(cw, VERLI, z-eig)
    1354              : #endif
    1355              : 
    1356              :     ! e1=e2=e3
    1357            0 :     elseif ( E12+E23 .lt. tol ) then
    1358              : #if 0
    1359              :         !print *, "e1=e2=e3" ! diff wrt simteta
    1360              :         cw(1)=f*third - (EZ4*f**2)*half + EZ4**2*f**3 + EZ4**3*f**4*Log(EZ4/EZ3)
    1361              :         cw(2)=f*third - (EZ4*f**2)*half + EZ4**2*f**3 + EZ4**3*f**4*Log(EZ4/EZ3)
    1362              :         cw(3)=f*third - (EZ4*f**2)*half + EZ4**2*f**3 + EZ4**3*f**4*Log(EZ4/EZ3)
    1363              :         cw(4)=-f + (3*EZ3*f**2)*half - 3*EZ3*EZ4*f**3 + 3*EZ3*EZ4**2*f**4*Log(EZ3/EZ4)
    1364              : #else
    1365            0 :         call SIM0TWOI(cw, VERLI, z-eig)
    1366              : #endif
    1367              :     ! e1=e2 e3=e4
    1368            0 :     elseif ( E12+E34 .lt. tol ) then
    1369              : #if 0
    1370              :         !print *, "e1=e2 e3=e4"    ! FIXME This is Buggy, does not work even with parabolic dispersion
    1371              :         cw(1)=-d - (3*d**2*EZ2)*half + 3*d**3*EZ2*EZ3 + 3*d**4*EZ2*EZ3**2*Log(EZ2/EZ3)
    1372              :         cw(2)=-d - (3*d**2*EZ2)*half + 3*d**3*EZ2*EZ3 + 3*d**4*EZ2*EZ3**2*Log(EZ2/EZ3)
    1373              :         cw(3)=d - (3*d**2*EZ3)*half - 3*d**3*EZ2*EZ3 + 3*d**4*EZ2**2*EZ3*Log(EZ3/EZ2)
    1374              :         cw(4)=d - (3*d**2*EZ3)*half - 3*d**3*EZ2*EZ3 + 3*d**4*EZ2**2*EZ3*Log(EZ3/EZ2)
    1375              : #else
    1376              :         !cw(1) = nine * EZ3**2 * EZ2 / E23**4 * log(EZ2/EZ3) * EZ2 * (EZ3 -E23)/E23**3 - one/E23
    1377              :         !cw(2) = cw(1)
    1378              :         !cw(3) = nine * EZ2**2 * EZ3 / E23**4 * log(EZ3/EZ2) * EZ3 * (EZ2 +E23)/E23**3 + one/E23
    1379              :         !cw(4) = cw(3)
    1380            0 :         call SIM0TWOI(cw, VERLI, z-eig)
    1381              :         !cw = zero
    1382              : #endif
    1383              : 
    1384              :     !       e3=e4
    1385            0 :     elseif ( E34 .lt. tol ) then
    1386              :         !print *, "e3=e4"
    1387              : #if 0
    1388              :         cw(1)=-(a*b**2*EZ1**2*(-1 + (a*EZ2 + 2*b*EZ3)*Log(EZ1))) + a**2*d**2*EZ2**3*Log(EZ2) - &
    1389              :                 b**2*d*EZ3**2*(1 + (2*b*EZ1 + d*EZ2)*Log(EZ3))
    1390              :         cw(2)=a**2*b**2*EZ1**3*Log(EZ1) - a*d**2*EZ2**2*(1 + (a*EZ1 - 2*d*EZ3)*Log(EZ2)) - &
    1391              :               b*d**2*EZ3**2*(1 + (b*EZ1 + 2*d*EZ2)*Log(EZ3))
    1392              :         cw(3)=a*b**3*EZ1**3*Log(EZ1) - a*d**3*EZ2**3*Log(EZ2) + b*d*EZ3*(half + b*EZ1 + d*EZ2 + &
    1393              :              (b**2*EZ1**2 + b*d*EZ1*EZ2 + d**2*EZ2**2)*Log(EZ3))
    1394              :         cw(4)=a*b**3*EZ1**3*Log(EZ1) - a*d**3*EZ2**3*Log(EZ2) + b*d*EZ3*(half + b*EZ1 + d*EZ2 + &
    1395              :              (b**2*EZ1**2 + b*d*EZ1*EZ2 + d**2*EZ2**2)*Log(EZ3))
    1396              : #else
    1397            0 :         call SIM0TWOI(cw, VERLI, z-eig)
    1398              : #endif
    1399              :     !    e2=e3
    1400            0 :     elseif ( E23 .lt. tol ) then
    1401              : #if 0
    1402              :         !print *, "e2=e3"
    1403              :         cw(1)=-(a**2*c*EZ1**2*(-1 + (2*a*EZ2 + c*EZ4)*Log(EZ1))) + &
    1404              :                 a**2*e*EZ2**2*(1 + (2*a*EZ1 - e*EZ4)*Log(EZ2)) + c**2*e**2*EZ4**3*Log(EZ4)
    1405              :         cw(2)=a**3*c*EZ1**3*Log(EZ1) - &
    1406              :               a*e*EZ2*(half + a*EZ1 - e*EZ4 + (a**2*EZ1**2 - a*e*EZ1*EZ4 + e**2*EZ4**2)*Log(EZ2)) + c*e**3*EZ4**3*Log(EZ4)
    1407              :         cw(3)=a**3*c*EZ1**3*Log(EZ1) - &
    1408              :               a*e*EZ2*(half + a*EZ1 - e*EZ4 + (a**2*EZ1**2 - a*e*EZ1*EZ4 + e**2*EZ4**2)*Log(EZ2)) + c*e**3*EZ4**3*Log(EZ4)
    1409              :         cw(4)=a**2*c**2*EZ1**3*Log(EZ1) - &
    1410              :               a*e**2*EZ2**2*(1 + (a*EZ1 - 2*e*EZ4)*Log(EZ2)) - c*e**2*EZ4**2*(1 + (c*EZ1 + 2*e*EZ2)*Log(EZ4))
    1411              : #else
    1412            0 :         call SIM0TWOI(cw, VERLI, z-eig)
    1413              : #endif
    1414              : 
    1415              :     ! e1=e2
    1416            0 :     elseif ( E12 .lt. tol ) then
    1417              :         !print *, "e1=e2"
    1418              : #if 0
    1419              :         cw(1)=b*c*EZ1*(half - b*EZ3 - c*EZ4 + (b**2*EZ3**2 + b*c*EZ3*EZ4 + c**2*EZ4**2)*Log(EZ1)) - &
    1420              :               b**3*EZ3**3*f*Log(EZ3) + c**3*EZ4**3*f*Log(EZ4)
    1421              :         cw(2)=b*c*EZ1*(half - b*EZ3 - c*EZ4 + (b**2*EZ3**2 + b*c*EZ3*EZ4 + c**2*EZ4**2)*Log(EZ1)) - &
    1422              :               b**3*EZ3**3*f*Log(EZ3) + c**3*EZ4**3*f*Log(EZ4)
    1423              :         cw(3)=-(b**2*c*EZ1**2*(-1 + (2*b*EZ3 + c*EZ4)*Log(EZ1))) + &
    1424              :                 b**2*EZ3**2*f*(1 + (2*b*EZ1 - EZ4*f)*Log(EZ3)) + c**2*EZ4**3*f**2*Log(EZ4)
    1425              :         cw(4)=-(b*c**2*EZ1**2*(-1 + (b*EZ3 + 2*c*EZ4)*Log(EZ1))) + &
    1426              :                 b**2*EZ3**3*f**2*Log(EZ3) - c**2*EZ4**2*f*(1 + (2*c*EZ1 + EZ3*f)*Log(EZ4))
    1427              : #else
    1428            0 :         call SIM0TWOI(cw, VERLI, z-eig)
    1429              : #endif
    1430              :     ! e1<e2<e3<e4
    1431              :     else
    1432              :         !print *, "e1<e2<e3<e4"
    1433              : #if 0
    1434              :         cw(1)=a**2*d*e*EZ2**3*Log(EZ2/EZ1) - b**2*d*EZ3**3*f*Log(EZ3/EZ1) + c*(a*b*EZ1**2 + c*e*EZ4**3*f*Log(EZ4/EZ1))
    1435              :         cw(2)=a**2*b*c*EZ1**3*Log(EZ1/EZ2) - b*d**2*EZ3**3*f*Log(EZ3/EZ2) + e*(-(a*d*EZ2**2) + c*e*EZ4**3*f*Log(EZ4/EZ2))
    1436              :         cw(3)=a*b**2*c*EZ1**3*Log(EZ1/EZ3) - a*d**2*e*EZ2**3*Log(EZ2/EZ3) + f*(b*d*EZ3**2 + c*e*EZ4**3*f*Log(EZ4/EZ3))
    1437              :         cw(4)=a*b*c**2*EZ1**3*Log(EZ1/EZ4) - a*d*e**2*EZ2**3*Log(EZ2/EZ4) + f*(-(c*e*EZ4**2) + b*d*EZ3**3*f*Log(EZ3/EZ4))
    1438              : #else
    1439              :         !do ii=1,4
    1440              :         !  cw(ii) = zme(ii) ** 2 / prod_wo(ii)
    1441              :         !  do jj=1,4
    1442              :         !    if (jj == ii) cycle
    1443              :         !    cw(ii) = cw(ii) + (zme(jj)**3 / prod_wo(jj) * log(zme(jj) / zme(ii)) / (eig(ii) - eig(jj)))
    1444              :         !  end do
    1445              :         !end do
    1446              : 
    1447            0 :         call SIM0TWOI(cw, VERLI, z-eig)
    1448              : #endif
    1449              :     endif
    1450              : 
    1451              :     ! HM:check this
    1452              :     !cw = cw * two
    1453              : 
    1454              :  contains
    1455              :  pure real(dp) function prod_wo(ii)
    1456              :     integer,intent(in) :: ii
    1457              :     integer  :: kk
    1458              : 
    1459              :     prod_wo = one
    1460              :     do kk=1,4
    1461              :        if (kk == ii) cycle
    1462              :        prod_wo = prod_wo * (eig(kk) - eig(ii))
    1463              :     end do
    1464              :  end function prod_wo
    1465              : 
    1466              : end subroutine get_onetetra_lambinvigneron
    1467              : !!***
    1468              : 
    1469              : !!****f* m_htetra/get_ontetratra_lambinvigneron_imag
    1470              : !! NAME
    1471              : !! get_ontetratra_lambinvigneron_imag
    1472              : !!
    1473              : !! FUNCTION
    1474              : !!  Compute the complex weights according to:
    1475              : !!  P. Lambin and J.P. Vigneron, Phys. Rev. B 29, 3430 (1984)
    1476              : !!  This routine is adapted from tdep where it was implemented
    1477              : !!  by Olle Hellman, all credits go to him
    1478              : !!
    1479              : !! INPUTS
    1480              : !!
    1481              : !! OUTPUT
    1482              : !!
    1483              : !! SOURCE
    1484              : 
    1485            0 : pure subroutine get_onetetetra_lambinvigneron_imag(eig, energies, nene, wt)
    1486              : 
    1487              :  ! dispersion values at the corners of the tetrahedron
    1488              :  real(dp), intent(in), dimension(4) :: eig
    1489              :  ! number of energies
    1490              :  integer, intent(in) :: nene
    1491              :  ! energy to evaluate the weights at
    1492              :  real(dp), intent(in) :: energies(nene)
    1493              :  ! integration weights
    1494              :  real(dp), intent(out) :: wt(4,nene)
    1495              : 
    1496              :  integer :: ie
    1497              :  real(dp) :: z
    1498              :  real(dp) :: EZ1,EZ2,EZ3,EZ4
    1499              :  real(dp) :: Emin,Emax
    1500              :  real(dp) :: E12,E13,E14,E23,E24,E34
    1501              :  real(dp) :: a,b,c,d,e,f,ff0,ff1,ff2,ff3,gg0,gg1,gg2,gg3,hh0,hh1,hh2,hh3,ii0,ii1,ii2,ii3
    1502              : 
    1503            0 :  wt = zero
    1504              :  Emin = eig(1)
    1505              :  Emax = eig(4)
    1506              : 
    1507            0 :  do ie=1,nene
    1508            0 :    z = energies(ie)
    1509            0 :    if (z<eig(1)) then ! e<e1<e2<e3<e4
    1510              :      cycle
    1511            0 :    else if (z .lt. eig(2)) then ! e1<e<e2<e3<e4
    1512            0 :      EZ1=z-eig(1)
    1513            0 :      EZ2=z-eig(2)
    1514            0 :      EZ3=z-eig(3)
    1515            0 :      EZ4=z-eig(4)
    1516            0 :      E12=eig(2)-eig(1)
    1517            0 :      E13=eig(3)-eig(1)
    1518            0 :      E14=eig(4)-eig(1)
    1519            0 :      a=one/E12
    1520            0 :      b=one/E13
    1521            0 :      c=one/E14
    1522            0 :      wt(1,ie)=a*b*c*EZ1**2*(-a*EZ2 - b*EZ3 - c*EZ4)
    1523            0 :      wt(2,ie)=a**2*b*c*EZ1**3
    1524            0 :      wt(3,ie)=a*b**2*c*EZ1**3
    1525            0 :      wt(4,ie)=a*b*c**2*EZ1**3
    1526            0 :      cycle
    1527            0 :    else if (z .lt. eig(3)) then ! e1<e2<e<e3<e4
    1528            0 :      EZ1=z-eig(1)
    1529            0 :      EZ2=z-eig(2)
    1530            0 :      EZ3=z-eig(3)
    1531            0 :      EZ4=z-eig(4)
    1532            0 :      E13=eig(3)-eig(1)
    1533            0 :      E14=eig(4)-eig(1)
    1534            0 :      E23=eig(3)-eig(2)
    1535            0 :      E24=eig(4)-eig(2)
    1536            0 :      b=one/E13
    1537            0 :      c=one/E14
    1538            0 :      d=one/E23
    1539            0 :      e=one/E24
    1540            0 :      ff0=-b**2*EZ3
    1541            0 :      ff2=-c**2*EZ4
    1542            0 :      gg0=-d**2*EZ3
    1543            0 :      gg2=-e**2*EZ4
    1544            0 :      hh0=d**2*EZ2
    1545            0 :      hh2=b**2*EZ1
    1546            0 :      ii0=e**2*EZ2
    1547            0 :      ii2=c**2*EZ1
    1548            0 :      ff1=-c*d*EZ1*EZ3-d*e*EZ2*EZ3-c*e*EZ1*EZ4
    1549            0 :      ff3=-b*d*EZ1*EZ3-b*e*EZ1*EZ4-d*e*EZ2*EZ4
    1550            0 :      gg1=-b*c*EZ1*EZ3-b*e*EZ2*EZ3-c*e*EZ2*EZ4
    1551            0 :      gg3=-b*d*EZ2*EZ3-b*c*EZ1*EZ4-c*d*EZ2*EZ4
    1552            0 :      hh1=-b*c*EZ1*EZ3-b*e*EZ2*EZ3-c*e*EZ2*EZ4
    1553            0 :      hh3=-c*d*EZ1*EZ3-d*e*EZ2*EZ3-c*e*EZ1*EZ4
    1554            0 :      ii1=-b*d*EZ2*EZ3-b*c*EZ1*EZ4-c*d*EZ2*EZ4
    1555            0 :      ii3=-b*d*EZ1*EZ3-b*e*EZ1*EZ4-d*e*EZ2*EZ4
    1556            0 :      wt(1,ie)=half*(ff0*ff1+ff2*ff3)
    1557            0 :      wt(2,ie)=half*(gg0*gg1+gg2*gg3)
    1558            0 :      wt(3,ie)=half*(hh0*hh1+hh2*hh3)
    1559            0 :      wt(4,ie)=half*(ii0*ii1+ii2*ii3)
    1560            0 :      cycle
    1561            0 :    else if (z .lt. eig(4)) then ! e1<e2<e3<e<e4
    1562            0 :      EZ1=z-eig(1)
    1563            0 :      EZ2=z-eig(2)
    1564            0 :      EZ3=z-eig(3)
    1565            0 :      EZ4=z-eig(4)
    1566            0 :      E14=eig(4)-eig(1)
    1567            0 :      E24=eig(4)-eig(2)
    1568            0 :      E34=eig(4)-eig(3)
    1569            0 :      c=one/E14
    1570            0 :      e=one/E24
    1571            0 :      f=one/E34
    1572            0 :      wt(1,ie)=-(c**2*e*EZ4**3*f)
    1573            0 :      wt(2,ie)=-(c*e**2*EZ4**3*f)
    1574            0 :      wt(3,ie)=-(c*e*EZ4**3*f**2)
    1575            0 :      wt(4,ie)=c*e*EZ4**2*f*(c*EZ1 + e*EZ2 + EZ3*f)
    1576            0 :      cycle
    1577              :    else
    1578            0 :      exit
    1579              :    end if
    1580              :  end do
    1581            0 :  wt = wt*4.0_dp
    1582              : 
    1583            0 : end subroutine get_onetetetra_lambinvigneron_imag
    1584              : !!***
    1585              : 
    1586              : !----------------------------------------------------------------------
    1587              : 
    1588              : !!****f* m_htetra/htetra_get_onewk_wvals
    1589              : !! NAME
    1590              : !! htetra_get_onewk_wvals
    1591              : !!
    1592              : !! FUNCTION
    1593              : !! Calculate integration weights and their derivatives for a single k-point in the IBZ.
    1594              : !!
    1595              : !! INPUTS
    1596              : !! ik_ibz=Index of the k-point in the IBZ array
    1597              : !! bcorr=1 to include Blochl correction else 0.
    1598              : !! nw=number of energies in wvals
    1599              : !! nibz=number of irreducible kpoints
    1600              : !! wvals(nw)=Frequency points.
    1601              : !! eigen_ibz(nkibz)=eigenenergies for each k point
    1602              : !!
    1603              : !! OUTPUT
    1604              : !!  weights(nw,2) = integration weights for
    1605              : !!    Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
    1606              : !!    for a given (band, k-point, spin).
    1607              : !!
    1608              : !! SOURCE
    1609              : 
    1610       100721 : subroutine htetra_get_onewk_wvals(tetra, ik_ibz, opt, nw, wvals, max_occ, nkibz, eig_ibz, weights)
    1611              : 
    1612              : !Arguments ------------------------------------
    1613              : !scalars
    1614              :  class(htetra_t), intent(inout) :: tetra
    1615              :  integer,intent(in) :: ik_ibz,nw,nkibz,opt
    1616              :  real(dp),intent(in) :: max_occ
    1617              : !arrays
    1618              :  real(dp),intent(in) :: wvals(nw), eig_ibz(nkibz)
    1619              :  real(dp),intent(out) :: weights(nw, 2)
    1620              : 
    1621              : !Local variables-------------------------------
    1622              : !scalars
    1623              :  integer  :: itetra,isummit,tetra_count,tetra_total
    1624              :  real(dp) :: tweight
    1625              : !arrays
    1626              :  integer  :: ind_ibz(4),tetra_mibz(0:4)
    1627       100721 :  real(dp) :: eig(4), tweight_tmp(4,nw),dweight_tmp(4,nw)
    1628              : ! *********************************************************************
    1629              : 
    1630    224806779 :  weights = zero
    1631              :  ! lazy evaluation of the mapping from k-points to tetrahedra
    1632       100721 :  if (.not.allocated(tetra%ibz)) call htetra_init_mapping_ibz(tetra)
    1633              : 
    1634              :  ! For each tetrahedron that belongs to this k-point
    1635       100721 :  tetra_count = tetra%tetra_count(ik_ibz)
    1636       100721 :  tetra_total = tetra%tetra_total(ik_ibz)
    1637     15810881 :  do itetra=1,tetra_count
    1638              : 
    1639     15710160 :    call htetra_get_ibz(tetra, ik_ibz, itetra, tetra_mibz)
    1640     15710160 :    tweight = one*tetra_mibz(0) / tetra_total
    1641     78550800 :    do isummit=1,4
    1642              :      ! Get mapping of each summit to eig_ibz
    1643     62840640 :      ind_ibz(isummit) = tetra_mibz(isummit)
    1644     78550800 :      eig(isummit) = eig_ibz(ind_ibz(isummit))
    1645              :    end do
    1646              : 
    1647              :    ! Sort energies before calling get_onetetra_blochl
    1648     15710160 :    call sort_4tetra(eig, ind_ibz)
    1649              : 
    1650              :    ! HM: Here we should only compute what we will use!
    1651     31420320 :    select case (opt)
    1652              :    case (0:1)
    1653     15710160 :      call get_onetetra_blochl(eig, wvals, nw, opt, tweight_tmp, dweight_tmp)
    1654              :    case (2)
    1655            0 :      call get_onetetetra_lambinvigneron_imag(eig, wvals, nw, dweight_tmp)
    1656     15710160 :      tweight_tmp = zero
    1657              :    end select
    1658              : 
    1659              :    ! Accumulate contributions to ik_ibz (there might be multiple vertices that map onto ik_ibz)
    1660     38922106 :    do isummit=1,4
    1661     38821385 :      if (ind_ibz(isummit) /= ik_ibz) cycle
    1662  13286034336 :      weights(:,1) = weights(:,1) + dweight_tmp(isummit,:)*tweight*max_occ
    1663  13286034336 :      weights(:,2) = weights(:,2) + tweight_tmp(isummit,:)*tweight*max_occ
    1664              :      ! HM: This exit is important, avoids summing the same contribution more than once
    1665     23111225 :      exit
    1666              :    end do
    1667              :  end do ! itetra
    1668              : 
    1669       100721 : end subroutine htetra_get_onewk_wvals
    1670              : !!***
    1671              : 
    1672              : !----------------------------------------------------------------------
    1673              : 
    1674              : !!****f* m_htetra/tetra_get_onewk
    1675              : !! NAME
    1676              : !! tetra_get_onewk
    1677              : !!
    1678              : !! FUNCTION
    1679              : !! Calculate integration weights and their derivatives for a single k-point in the IBZ.
    1680              : !! Same as above but different calling arguments.
    1681              : !! IBZ Weights are not included
    1682              : !! HM: The above is preferred but I keep this one to ease the transition
    1683              : !!
    1684              : !! INPUTS
    1685              : !!
    1686              : !! OUTPUT
    1687              : !!
    1688              : !! SOURCE
    1689              : 
    1690        12326 : subroutine htetra_get_onewk(tetra, ik_ibz, bcorr, nw, nkibz, eig_ibz, enemin, enemax, max_occ, weights)
    1691              : 
    1692              : !Arguments ------------------------------------
    1693              : !scalars
    1694              :  class(htetra_t), intent(inout) :: tetra
    1695              :  integer,intent(in) :: ik_ibz,nw,nkibz,bcorr
    1696              :  real(dp) ,intent(in) :: enemin,enemax,max_occ
    1697              : !arrays
    1698              :  real(dp),intent(in) :: eig_ibz(nkibz)
    1699              :  real(dp),intent(out) :: weights(nw,2)
    1700              : 
    1701              : !Local variables-------------------------------
    1702              : !scalars
    1703        12326 :  real(dp) :: wvals(nw)
    1704              : ! *********************************************************************
    1705              : 
    1706     63510798 :  weights = zero
    1707        12326 :  wvals = linspace(enemin, enemax, nw)
    1708        12326 :  call htetra_get_onewk_wvals(tetra, ik_ibz, bcorr, nw, wvals, max_occ, nkibz, eig_ibz, weights)
    1709              : 
    1710        12326 : end subroutine htetra_get_onewk
    1711              : !!***
    1712              : 
    1713              : !----------------------------------------------------------------------
    1714              : 
    1715              : !!****f* m_htetra/htetra_get_onewk_wvals_zinv
    1716              : !! NAME
    1717              : !! htetra_get_onewk_wvals_zinv
    1718              : !!
    1719              : !! FUNCTION
    1720              : !! Calculate integration weights for 1/(z-E(k)) for a single k-point in the IBZ.
    1721              : !! Using either the implementation from:
    1722              : !! S. Kaprzyk, Computer Physics Communications 183, 347 (2012).
    1723              : !! or (TODO)
    1724              : !! P. Lambin and J.P. Vigneron, Phys. Rev. B 29, 3430 (1984).
    1725              : !!
    1726              : !! INPUTS
    1727              : !! ik_ibz=Index of the k-point in the IBZ array
    1728              : !! bcorr=1 to include Blochl correction else 0.
    1729              : !! nw=number of energies in wvals
    1730              : !! nibz=number of irreducible kpoints
    1731              : !! wvals(nw)=Frequency points.
    1732              : !! eigen_ibz(nkibz)=eigenenergies for each k point
    1733              : !! opt: 1 for S. Kaprzyk routines, 2 for Lambin.
    1734              : !!
    1735              : !! OUTPUT
    1736              : !!  weights(nw,2) = integration weights for
    1737              : !!    Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
    1738              : !!    for a given (band, k-point, spin).
    1739              : !!  [erange(2)]: if present, weights are computed with an approximated asyntotic expression if
    1740              : !!   real(z) is outside of this interval and with tetra if inside.
    1741              : !!
    1742              : !! SOURCE
    1743              : 
    1744            0 : subroutine htetra_get_onewk_wvals_zinv(tetra, ik_ibz, nz, zvals, max_occ, nkibz, eig_ibz, opt, cweights, erange)
    1745              : 
    1746              : !Arguments ------------------------------------
    1747              : !scalars
    1748              :  class(htetra_t), intent(inout) :: tetra
    1749              :  integer,intent(in) :: ik_ibz,nz,nkibz,opt
    1750              :  real(dp) ,intent(in) :: max_occ
    1751              : !arrays
    1752              :  complex(dp),intent(in) :: zvals(nz)
    1753              :  real(dp),optional,intent(in) :: erange(2)
    1754              :  real(dp),intent(in) :: eig_ibz(nkibz)
    1755              :  complex(dp),intent(out) :: cweights(nz)
    1756              : 
    1757              : !Local variables-------------------------------
    1758              : !scalars
    1759              :  integer  :: itetra,isummit,tetra_total,tetra_count,iz
    1760              :  real(dp) :: tweight
    1761              : !arrays
    1762              :  integer  :: ind_ibz(4),tetra_mibz(0:4)
    1763              :  real(dp) :: eig(4), my_erange(2)
    1764              :  complex(dp) :: verm(4), cw(4), verli(4)
    1765              : ! *********************************************************************
    1766              : 
    1767            0 :  cweights = zero
    1768              :  ! lazy evaluation of the mapping from k-points to tetrahedra
    1769            0 :  if (.not.allocated(tetra%ibz)) call htetra_init_mapping_ibz(tetra)
    1770              : 
    1771            0 :  if (all(opt /= [1, 2])) then
    1772            0 :    ABI_ERROR(sjoin("Invalid opt:", itoa(opt)))
    1773              :  end if
    1774              : 
    1775            0 :  my_erange = [-huge(one), huge(one)]; if (present(erange)) my_erange = erange
    1776              : 
    1777              :  ! For each tetrahedron that belongs to this k-point
    1778            0 :  tetra_count = tetra%tetra_count(ik_ibz)
    1779            0 :  tetra_total = tetra%tetra_total(ik_ibz)
    1780            0 :  do itetra=1,tetra_count
    1781              : 
    1782            0 :    call htetra_get_ibz(tetra, ik_ibz, itetra, tetra_mibz)
    1783            0 :    tweight = one * tetra_mibz(0) / tetra_total
    1784            0 :    do isummit=1,4
    1785              :      ! Get mapping of each summit to eig_ibz
    1786            0 :      ind_ibz(isummit) = tetra_mibz(isummit)
    1787            0 :      eig(isummit) = eig_ibz(ind_ibz(isummit))
    1788              :    end do
    1789              : 
    1790              :    ! Loop over frequencies
    1791            0 :    do iz=1,nz
    1792              : 
    1793            0 :      if (real(zvals(iz)) >= my_erange(1) .and. real(zvals(iz)) <= my_erange(2)) then
    1794            0 :        select case(opt)
    1795              :        case (1)
    1796            0 :          verm = zvals(iz) - eig
    1797            0 :          call SIM0TWOI(cw, VERLI, VERM)
    1798              :        case (2)
    1799            0 :          call get_onetetra_lambinvigneron(eig, zvals(iz), cw)
    1800              :        end select
    1801              :      else
    1802            0 :        cw = (one / (zvals(iz) - eig)) / four !* tetra%vv
    1803              :      end if
    1804              : 
    1805            0 :      do isummit=1,4
    1806            0 :        if (ind_ibz(isummit) /= ik_ibz) cycle
    1807            0 :        cweights(iz) = cweights(iz) + cw(isummit) * tweight * max_occ
    1808              :        ! HM: This exit is important, avoids summing the same contribution more than once
    1809            0 :        exit
    1810              :      end do
    1811              :    end do
    1812              :  end do ! itetra
    1813              : 
    1814            0 : end subroutine htetra_get_onewk_wvals_zinv
    1815              : !!***
    1816              : 
    1817              : !----------------------------------------------------------------------
    1818              : 
    1819              : !!****f* m_htetra/htetra_get_delta_mask
    1820              : !! NAME
    1821              : !!  htetra_get_delta_mask
    1822              : !!
    1823              : !! FUNCTION
    1824              : !!  Get a mask for the kpoints where the delta is finite
    1825              : !!
    1826              : 
    1827              : subroutine htetra_get_delta_mask(tetra, eig_ibz, wvals, nw, nkpt, kmask, comm)
    1828              : 
    1829              : !Arguments
    1830              :  class(htetra_t), intent(in) :: tetra
    1831              :  integer,intent(in) :: nw,nkpt,comm
    1832              :  real(dp),intent(in) :: wvals(nw)
    1833              :  real(dp),intent(in) :: eig_ibz(nkpt)
    1834              :  integer,intent(out) :: kmask(nkpt)
    1835              : 
    1836              : !Local variables-------------------------------
    1837              :  integer :: ik_ibz,nprocs,my_rank,ierr, contrib
    1838              :  integer :: tetra_count, itetra, isummit, ihash
    1839              :  real(dp) :: emin,emax
    1840              :  integer :: ind_ibz(4)
    1841              :  real(dp) :: eig(4)
    1842              : 
    1843              :  nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
    1844              :  kmask = 0
    1845              :  ! For each bucket of tetrahedra
    1846              :  do ihash=1,tetra%nbuckets
    1847              :    if (mod(ihash,nprocs) /= my_rank) cycle
    1848              : 
    1849              :    ! For each tetrahedron
    1850              :    tetra_count = size(tetra%unique_tetra(ihash)%indexes, dim=2)
    1851              :    do itetra=1,tetra_count
    1852              : 
    1853              :      ! Get mapping of each summit to eig_ibz
    1854              :      do isummit=1,4
    1855              :        ind_ibz(isummit) = tetra%unique_tetra(ihash)%indexes(isummit, itetra)
    1856              :        eig(isummit) = eig_ibz(ind_ibz(isummit))
    1857              :      end do
    1858              : 
    1859              :      ! Determine the energy range of the tetrahedra
    1860              :      emin = minval(eig)
    1861              :      emax = maxval(eig)
    1862              : 
    1863              :      ! Check if any value in wvals is between emin and emax
    1864              :      contrib = 0; if (any(emin < wvals .and. wvals < emax)) contrib = 1
    1865              : 
    1866              :      ! Compute the union
    1867              :      do isummit=1,4
    1868              :        ik_ibz = ind_ibz(isummit)
    1869              :        kmask(ik_ibz) = kmask(ik_ibz) + contrib
    1870              :      end do
    1871              :    end do ! itetra
    1872              :  end do
    1873              : 
    1874              :  call xmpi_sum(kmask, comm, ierr)
    1875              : 
    1876              : end subroutine htetra_get_delta_mask
    1877              : !!***
    1878              : 
    1879              : !----------------------------------------------------------------------
    1880              : 
    1881              : !!****f* m_htetra/htetra_wvals_weights
    1882              : !! NAME
    1883              : !!  htetra_wvals_weights
    1884              : !!
    1885              : !! FUNCTION
    1886              : !!   Emulates the behaviour of the previous tetrahedron implementation but
    1887              : !!   taking a list of energies as input.
    1888              : !!
    1889              : !!   HM: I find that in many routines its better to change the implementation
    1890              : !!   and accumulate the tetrahedron weights in the same way as the
    1891              : !!   gaussian smearing weights using htetra_get_onewk_wvals. However this requires
    1892              : !!   some refactoring of the code. I provide this routine to make it easier
    1893              : !!   to transition to the new tetrahedron implementation without refactoring.
    1894              : !!   Looping over tetrahedra (i.e. using tetra_blochl_weights) is currently faster
    1895              : !!   than looping over k-points.
    1896              : !!
    1897              : !!   MG: Note, however, that tetra_blochl_weights requires more memory as
    1898              : !!       one has to allocate dweight(nw,nkpt),tweight(nw,nkpt) and the size of the arrays increases
    1899              : !!       quickly with the k-mesh and the number of frequencies (propto mband)
    1900              : !!
    1901              : !! INPUTS
    1902              : !!
    1903              : !! OUTPUT
    1904              : !!
    1905              : !! SOURCE
    1906              : 
    1907          118 : subroutine htetra_wvals_weights(tetra, eig_ibz, nw, wvals, max_occ, nkpt, opt, tweight, dweight, comm)
    1908              : 
    1909              : !Arguments ------------------------------------
    1910              : !scalars
    1911              :  integer,intent(in) :: nw,nkpt,opt,comm
    1912              :  class(htetra_t), intent(in) :: tetra
    1913              :  real(dp) ,intent(in) :: max_occ
    1914              : !arrays
    1915              :  real(dp),intent(in) :: eig_ibz(nkpt)
    1916              :  real(dp),intent(out) :: dweight(nw,nkpt),tweight(nw,nkpt)
    1917              : 
    1918              : !Local variables-------------------------------
    1919              : !scalars
    1920              :  integer :: ik_ibz,multiplicity,nprocs,my_rank,ierr
    1921              :  integer :: tetra_count, itetra, isummit, ihash
    1922              : !arrays
    1923              :  integer :: ind_ibz(4)
    1924          118 :  real(dp) :: eig(4), wvals(nw), dweight_tmp(4,nw),tweight_tmp(4,nw)
    1925              : ! *********************************************************************
    1926              : 
    1927     10409956 :  tweight = zero; dweight = zero
    1928          118 :  nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
    1929              : 
    1930              :  ! For each bucket of tetrahedra
    1931         5994 :  do ihash=1,tetra%nbuckets
    1932         5876 :    if (mod(ihash, nprocs) /= my_rank) cycle
    1933              : 
    1934              :    ! For each tetrahedron
    1935         5876 :    tetra_count = size(tetra%unique_tetra(ihash)%indexes, dim=2)
    1936       105152 :    do itetra=1,tetra_count
    1937              : 
    1938              :      ! Get mapping of each summit to eig_ibz
    1939       495790 :      do isummit=1,4
    1940       396632 :        ind_ibz(isummit) = tetra%unique_tetra(ihash)%indexes(isummit, itetra)
    1941       495790 :        eig(isummit) = eig_ibz(ind_ibz(isummit))
    1942              :      end do
    1943              : 
    1944              :      ! Sort energies before calling get_onetetra_blochl
    1945        99158 :      call sort_4tetra(eig, ind_ibz)
    1946              : 
    1947              :      ! Get tetrahedron weights
    1948       198316 :      select case (opt)
    1949              :      case (0:1)
    1950        99158 :        call get_onetetra_blochl(eig, wvals, nw, opt, tweight_tmp, dweight_tmp)
    1951              :      case (2)
    1952            0 :        call get_onetetetra_lambinvigneron_imag(eig, wvals, nw, dweight_tmp)
    1953        99158 :        tweight_tmp = zero
    1954              :      end select
    1955              : 
    1956              :      ! Accumulate the contributions
    1957        99158 :      multiplicity = tetra%unique_tetra(ihash)%indexes(0, itetra)
    1958       501666 :      do isummit=1,4
    1959       396632 :        ik_ibz = ind_ibz(isummit)
    1960    337052272 :        dweight(:,ik_ibz) = dweight(:,ik_ibz) + dweight_tmp(isummit,:) * multiplicity * max_occ
    1961    337151430 :        tweight(:,ik_ibz) = tweight(:,ik_ibz) + tweight_tmp(isummit,:) * multiplicity * max_occ
    1962              :      end do
    1963              :    end do ! itetra
    1964              :  end do
    1965              : 
    1966              :  ! Rescale weights
    1967          118 :  select case(tetra%opt)
    1968              :  case (1)
    1969            0 :    do ik_ibz=1,tetra%nkibz
    1970            0 :      dweight(:,ik_ibz) = dweight(:,ik_ibz) * tetra%ibz_multiplicity(ik_ibz) / tetra%tetra_total(ik_ibz) / tetra%nkbz
    1971            0 :      tweight(:,ik_ibz) = tweight(:,ik_ibz) * tetra%ibz_multiplicity(ik_ibz) / tetra%tetra_total(ik_ibz) / tetra%nkbz
    1972              :    end do
    1973              :  case (2)
    1974      5204978 :    dweight = dweight*tetra%vv / 4.0_dp
    1975      5205096 :    tweight = tweight*tetra%vv / 4.0_dp
    1976              :  end select
    1977              : 
    1978          118 :  call xmpi_sum(dweight, comm, ierr)
    1979          118 :  call xmpi_sum(tweight, comm, ierr)
    1980              : 
    1981          118 : end subroutine htetra_wvals_weights
    1982              : !!***
    1983              : 
    1984              : !----------------------------------------------------------------------
    1985              : 
    1986              : !!****f* m_htetra/htetra_wvals_weights_delta
    1987              : !! NAME
    1988              : !!  htetra_wvals_weights_delta
    1989              : !!
    1990              : !! FUNCTION
    1991              : !!  Same as above but computing only delta for performance and memory
    1992              : !!  HM: Should find a clean way to avoid copy paste routine
    1993              : !!
    1994              : !! SOURCE
    1995              : 
    1996        30216 : subroutine htetra_wvals_weights_delta(tetra, eig_ibz, nw, wvals, max_occ, nkpt, opt, dweight, comm)
    1997              : 
    1998              : !Arguments ------------------------------------
    1999              : !scalars
    2000              :  class(htetra_t), intent(in) :: tetra
    2001              :  integer,intent(in) :: nw, nkpt, opt, comm
    2002              :  real(dp),intent(in) :: max_occ
    2003              : !arrays
    2004              :  real(dp),intent(in) :: eig_ibz(nkpt), wvals(nw)
    2005              :  real(dp),intent(out) :: dweight(nw, nkpt)
    2006              : 
    2007              : !Local variables-------------------------------
    2008              : !scalars
    2009              :  integer :: ik_ibz,multiplicity,nprocs,my_rank,ierr
    2010              :  integer :: tetra_count, itetra, isummit, ihash
    2011              : !arrays
    2012              :  integer :: ind_ibz(4)
    2013        30216 :  real(dp) :: eig(4), dweight_tmp(4,nw),tweight_tmp(4,nw)
    2014              : ! *********************************************************************
    2015              : 
    2016     13066728 :  dweight = zero
    2017        30216 :  nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
    2018              : 
    2019              :  ! For each bucket of tetrahedra
    2020      6548472 :  do ihash=1,tetra%nbuckets
    2021      6518256 :    if (mod(ihash, nprocs) /= my_rank) cycle
    2022              : 
    2023              :    ! For each tetrahedron
    2024      6518256 :    tetra_count = size(tetra%unique_tetra(ihash)%indexes, dim=2)
    2025    129322080 :    do itetra=1,tetra_count
    2026              : 
    2027              :      ! Get mapping of each summit to eig_ibz
    2028    613868040 :      do isummit=1,4
    2029    491094432 :        ind_ibz(isummit) = tetra%unique_tetra(ihash)%indexes(isummit,itetra)
    2030    613868040 :        eig(isummit) = eig_ibz(ind_ibz(isummit))
    2031              :      end do
    2032              : 
    2033              :      ! Sort energies before calling get_onetetra_blochl
    2034    122773608 :      call sort_4tetra(eig, ind_ibz)
    2035              : 
    2036              :      ! Get tetrahedron weights
    2037    245547216 :      select case (opt)
    2038              :      case (0:1)
    2039    122773608 :        call get_onetetra_blochl(eig, wvals, nw, opt, tweight_tmp, dweight_tmp)
    2040              :      case (2)
    2041    122773608 :        call get_onetetetra_lambinvigneron_imag(eig, wvals, nw, dweight_tmp)
    2042              :      end select
    2043              : 
    2044              :      ! Accumulate the contributions
    2045    122773608 :      multiplicity = tetra%unique_tetra(ihash)%indexes(0,itetra)
    2046    620386296 :      do isummit=1,4
    2047    491094432 :        ik_ibz = ind_ibz(isummit)
    2048   1104962472 :        dweight(:,ik_ibz) = dweight(:,ik_ibz) + dweight_tmp(isummit,:)*multiplicity*max_occ
    2049              :      end do
    2050              :    end do ! itetra
    2051              :  end do
    2052              : 
    2053              :  ! Rescale weights
    2054        30216 :  select case(tetra%opt)
    2055              :  case (1)
    2056            0 :    do ik_ibz=1,tetra%nkibz
    2057            0 :      dweight(:,ik_ibz) = dweight(:,ik_ibz) * tetra%ibz_multiplicity(ik_ibz) / tetra%tetra_total(ik_ibz) / tetra%nkbz
    2058              :    end do
    2059              :  case (2)
    2060     13066728 :    dweight = dweight * tetra%vv / 4.0_dp
    2061              :  end select
    2062              : 
    2063        30216 :  call xmpi_sum(dweight, comm, ierr)
    2064              : 
    2065        30216 : end subroutine htetra_wvals_weights_delta
    2066              : !!***
    2067              : 
    2068              : !----------------------------------------------------------------------
    2069              : 
    2070              : !!****f* m_htetra/htetra_blochl_weights
    2071              : !! NAME
    2072              : !!  htetra_blochl_weights
    2073              : !!
    2074              : !! FUNCTION
    2075              : !!   Emulates the behaviour of the previous tetrahedron implementation.
    2076              : !!   IBZ weights are included.
    2077              : !!
    2078              : !! INPUTS
    2079              : !!
    2080              : !! OUTPUT
    2081              : !!
    2082              : !! SOURCE
    2083              : 
    2084          118 : subroutine htetra_blochl_weights(tetra, eig_ibz, enemin, enemax, max_occ, nw, nkpt, bcorr, tweight, dweight, comm)
    2085              : 
    2086              : !Arguments ------------------------------------
    2087              : !scalars
    2088              :  class(htetra_t), intent(in) :: tetra
    2089              :  integer,intent(in) :: nw,nkpt, bcorr, comm
    2090              :  real(dp),intent(in) :: enemax, enemin, max_occ
    2091              : !arrays
    2092              :  real(dp),intent(in) :: eig_ibz(nkpt)
    2093              :  real(dp),intent(out) :: dweight(nw,nkpt), tweight(nw,nkpt)
    2094              : 
    2095              : !Local variables-------------------------------
    2096          236 :  real(dp) :: wvals(nw)
    2097              : ! *********************************************************************
    2098              : 
    2099          118 :  wvals = linspace(enemin, enemax, nw)
    2100          118 :  call htetra_wvals_weights(tetra,eig_ibz,nw,wvals,max_occ,nkpt,bcorr,tweight,dweight,comm)
    2101              : 
    2102          118 : end subroutine htetra_blochl_weights
    2103              : !!***
    2104              : 
    2105              : !----------------------------------------------------------------------
    2106              : 
    2107              : !!****f* m_htetra/htetra_blochl_weights_wvals_zinv
    2108              : !! NAME
    2109              : !!  htetra_blochl_weights_wvals_zinv
    2110              : !!
    2111              : !! FUNCTION
    2112              : !!  The same as htetra_get_onewk_wvals_zinv but looping over tetrahedra
    2113              : !!  which is more efficient
    2114              : !!
    2115              : !! INPUTS
    2116              : !! nz: Number of frequencies
    2117              : !! zvals(nw): z-values
    2118              : !! max_occ=maximal occupation number (2 for nsppol=1, 1 for nsppol=2)
    2119              : !! nkpt=number of irreducible kpoints
    2120              : !! zinv_opt:
    2121              : !!   1 for S. Kaprzyk routines,
    2122              : !!   2 for Lambin-Vigneron.
    2123              : !!  [erange(2)]: if present, weights are computed with a standard quadrature method if
    2124              : !!     real(z) is outside of this interval and with tetra if inside.
    2125              : !! comm=MPI communicator
    2126              : !!
    2127              : !! OUTPUT
    2128              : !!
    2129              : !! SOURCE
    2130              : 
    2131        18048 : subroutine htetra_weights_wvals_zinv(tetra, eig_ibz, nz, zvals, max_occ, nkpt, zinv_opt, cweight, comm, erange)
    2132              : 
    2133              : !Arguments ------------------------------------
    2134              : !scalars
    2135              :  integer,intent(in) :: nz, nkpt, zinv_opt, comm
    2136              :  class(htetra_t), intent(in) :: tetra
    2137              :  real(dp) ,intent(in) :: max_occ
    2138              : !arrays
    2139              :  real(dp),intent(in) :: eig_ibz(nkpt)
    2140              :  real(dp),optional,intent(in) :: erange(2)
    2141              :  complex(dp),intent(in)  :: zvals(nz)
    2142              :  complex(dp),intent(out) :: cweight(nz, nkpt)
    2143              : 
    2144              : !Local variables-------------------------------
    2145              : !scalars
    2146              :  integer :: ik_ibz, iz, multiplicity, nprocs, my_rank, ierr, ii, jj, kk, esumk
    2147              :  integer :: tetra_count, itetra, isummit, ihash
    2148              : !arrays
    2149              :  integer :: ind_ibz(4)
    2150              :  real(dp) :: eig(4), my_erange(2)
    2151              :  complex(dp) :: cw(4), verli(4), verm(4), aw(4), bw(4) !, cw_lw(4)
    2152        36096 :  real(dp) :: rwg(nz, 4)
    2153              : ! *********************************************************************
    2154              : 
    2155        18048 :  nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
    2156      8541696 :  cweight = zero
    2157              : 
    2158        18048 :  my_erange = [-huge(one), huge(one)]; if (present(erange)) my_erange = erange
    2159              : 
    2160              :  ! For each bucket of tetrahedra
    2161       207552 :  do ihash=1,tetra%nbuckets
    2162       189504 :    if (mod(ihash, nprocs) /= my_rank) cycle
    2163              : 
    2164              :    ! For each tetrahedron that belongs to this k-point
    2165       189504 :    tetra_count = size(tetra%unique_tetra(ihash)%indexes, dim=2)
    2166      1461888 :    do itetra=1,tetra_count
    2167              : 
    2168              :      ! Get mapping of each summit to eig_ibz
    2169      6271680 :      do isummit=1,4
    2170      5017344 :        ind_ibz(isummit) = tetra%unique_tetra(ihash)%indexes(isummit, itetra)
    2171      6271680 :        eig(isummit) = eig_ibz(ind_ibz(isummit))
    2172              :      end do
    2173              : 
    2174              :      ! Get multiplicity
    2175      1254336 :      multiplicity = tetra%unique_tetra(ihash)%indexes(0, itetra)
    2176              : 
    2177              :      ! Sort energies before calling get_onetetra_lambinvigneron
    2178              :      ! SIM0TWOI does not require sorted energies but since we call the routine
    2179              :      ! to fix get_onetetra_lambinvigneron we need to sort here.
    2180      1254336 :      call sort_4tetra(eig, ind_ibz)
    2181              : 
    2182      1443840 : if (zinv_opt == 1) then
    2183              :      ! Loop over frequencies
    2184     56418432 :      do iz=1,nz
    2185              : 
    2186              :        ! Get tetrahedron weights
    2187     55164096 :        if (real(zvals(iz)) >= my_erange(1) .and. real(zvals(iz)) <= my_erange(2)) then
    2188              : 
    2189     55164096 :          select case(zinv_opt)
    2190              :          case (1)
    2191    275820480 :            verm = zvals(iz) - eig
    2192     55164096 :            call SIM0TWOI(cw, VERLI, VERM)
    2193              : 
    2194              :            !call get_onetetra_lambinvigneron(eig, zvals(iz), cw_lw)
    2195              :            !if (any(abs(real(cw_lw(:)) / (real(cw(:)))) > 1.1)) then
    2196              :            !  do ierr=1,4
    2197              :            !    !write(std_out, *) "simte vs lw:", cw(ierr), cw_lw(ierr)
    2198              :            !    write(std_out, *) "cw_lw / (simtet)", cw_lw(ierr) / (cw(ierr))
    2199              :            !  end do
    2200              :            !end if
    2201              : 
    2202              :          case (2)
    2203              :            call get_onetetra_lambinvigneron(eig, zvals(iz), cw)
    2204              :          end select
    2205              : 
    2206              :        else
    2207              :          ! Use asymptotic expansion of integral for large z.
    2208            0 :          aw = (eig + sum(eig)) / five
    2209            0 :          do ii=1,4
    2210            0 :            bw(ii) = zero
    2211            0 :            do jj=1,4
    2212            0 :              if (jj == ii) cycle
    2213              :              esumk = zero
    2214            0 :              do kk=1,4
    2215            0 :                if (kk == jj) cycle
    2216            0 :                esumk = esumk + (eig(kk) - eig(jj)) ** 2
    2217              :              end do
    2218            0 :              bw(ii) = bw(ii) + three * (eig(jj) - eig(ii)) ** 2 + esumk
    2219              :            end do
    2220              :          end do
    2221            0 :          bw = bw / 300_dp
    2222            0 :          cw = one / (zvals(iz) - aw - bw / zvals(iz)) / four
    2223              :          !This for naive integration
    2224              :          !cw = (one / (zvals(iz) - eig)) / four
    2225              :        end if
    2226              : 
    2227              :        ! Accumulate contributions
    2228    277074816 :        do isummit=1,4
    2229    220656384 :          ik_ibz = ind_ibz(isummit)
    2230    275820480 :          cweight(iz, ik_ibz) = cweight(iz, ik_ibz) + cw(isummit) * multiplicity * max_occ
    2231              :        end do
    2232              : 
    2233              :      end do ! iz
    2234              : 
    2235              : else
    2236            0 :        call get_onetetra_ppart_lv(nz, real(zvals), eig, rwg)
    2237              : 
    2238            0 :        do iz=1,nz
    2239              :          ! Accumulate contributions
    2240            0 :          do isummit=1,4
    2241            0 :            ik_ibz = ind_ibz(isummit)
    2242            0 :            cweight(iz, ik_ibz) = cweight(iz, ik_ibz) + rwg(iz, isummit) * multiplicity * max_occ
    2243              :          end do
    2244              :        end do
    2245              : endif
    2246              : 
    2247              :    end do ! itetra
    2248              :  end do
    2249              : 
    2250              :  ! Rescale weights
    2251        18048 :  select case(tetra%opt)
    2252              :  case (1)
    2253            0 :    do ik_ibz=1,tetra%nkibz
    2254            0 :      cweight(:,ik_ibz) = cweight(:,ik_ibz) * tetra%ibz_multiplicity(ik_ibz) / tetra%nkbz / tetra%tetra_total(ik_ibz)
    2255              :    end do
    2256              :  case (2)
    2257      8541696 :    cweight = cweight * tetra%vv
    2258              :  end select
    2259              : 
    2260        18048 :  call xmpi_sum(cweight, comm, ierr)
    2261              : 
    2262        18048 : end subroutine htetra_weights_wvals_zinv
    2263              : !!***
    2264              : 
    2265              : !----------------------------------------------------------------------
    2266              : 
    2267              : !!****f* m_htetra/sort_4tetra
    2268              : !! NAME
    2269              : !!  sort_4tetra
    2270              : !!
    2271              : !! FUNCTION
    2272              : !!  Sort double precision array list(4) into ascending numerical order
    2273              : !!  while making corresponding rearrangement of the integer array iperm.
    2274              : !!
    2275              : !!  Taken from: https://stackoverflow.com/questions/6145364/sort-4-number-with-few-comparisons
    2276              : !!
    2277              : !! INPUTS
    2278              : !!  list(4) intent(inout) list of double precision numbers to be sorted
    2279              : !!  perm(4) intent(inout) iperm(i)=i (very important)
    2280              : !!
    2281              : !! OUTPUT
    2282              : !!  list(4) sorted list
    2283              : !!  perm(4) index of permutation given the right ascending order
    2284              : !!
    2285              : !! SOURCE
    2286              : 
    2287    139837262 : pure subroutine sort_4tetra(list, perm)
    2288              : 
    2289              :  integer,  intent(inout) :: perm(4)
    2290              :  real(dp), intent(inout) :: list(4)
    2291              : 
    2292              : !Local variables-------------------------------
    2293              :  integer :: ia,ib,ic,id,ilow1,ilow2,ihigh1,ihigh2
    2294              :  integer :: ilowest,ihighest,imiddle1,imiddle2
    2295              :  real(dp) :: va,vb,vc,vd,vlow1,vlow2,vhigh1,vhigh2
    2296              :  real(dp) :: vlowest,vhighest,vmiddle1,vmiddle2
    2297              : 
    2298    139837262 :  va = list(1); ia = perm(1)
    2299    139837262 :  vb = list(2); ib = perm(2)
    2300    139837262 :  vc = list(3); ic = perm(3)
    2301    139837262 :  vd = list(4); id = perm(4)
    2302              : 
    2303    139837262 :  if (va < vb) then
    2304              :      vlow1 = va; vhigh1 = vb
    2305              :      ilow1 = ia; ihigh1 = ib
    2306              :  else
    2307     72940132 :      vlow1 = vb; vhigh1 = va
    2308     72940132 :      ilow1 = ib; ihigh1 = ia
    2309              :  endif
    2310              : 
    2311    139837262 :  if (vc < vd) then
    2312              :      vlow2 = vc; vhigh2 = vd
    2313              :      ilow2 = ic; ihigh2 = id
    2314              :  else
    2315     73080767 :      vlow2 = vd; vhigh2 = vc
    2316     73080767 :      ilow2 = id; ihigh2 = ic
    2317              :  endif
    2318              : 
    2319    139837262 :  if (vlow1 < vlow2) then
    2320              :      vlowest  = vlow1; vmiddle1 = vlow2
    2321              :      ilowest  = ilow1; imiddle1 = ilow2
    2322              :  else
    2323     71288294 :      vlowest  = vlow2; vmiddle1 = vlow1
    2324     71288294 :      ilowest  = ilow2; imiddle1 = ilow1
    2325              :  endif
    2326              : 
    2327    139837262 :  if (vhigh1 > vhigh2) then
    2328              :      vhighest = vhigh1; vmiddle2 = vhigh2
    2329              :      ihighest = ihigh1; imiddle2 = ihigh2
    2330              :  else
    2331     69068729 :      vhighest = vhigh2; vmiddle2 = vhigh1
    2332     69068729 :      ihighest = ihigh2; imiddle2 = ihigh1
    2333              :  endif
    2334              : 
    2335    139837262 :  if (vmiddle1 < vmiddle2) then
    2336    365584920 :      list = [vlowest, vmiddle1, vmiddle2, vhighest]
    2337    365584920 :      perm = [ilowest, imiddle1, imiddle2, ihighest]
    2338              :  else
    2339    333601390 :      list = [vlowest, vmiddle2, vmiddle1, vhighest]
    2340    333601390 :      perm = [ilowest, imiddle2, imiddle1, ihighest]
    2341              :  endif
    2342              : 
    2343    139837262 : end subroutine sort_4tetra
    2344              : !!***
    2345              : 
    2346              : !----------------------------------------------------------------------
    2347              : 
    2348              : !!****f* m_numeric_tools/sort_4tetra_int
    2349              : !! NAME
    2350              : !!  sort_4tetra_int
    2351              : !!
    2352              : !! FUNCTION
    2353              : !!
    2354              : !! INPUTS
    2355              : !!
    2356              : !! OUTPUT
    2357              : !!
    2358              : !! SOURCE
    2359              : 
    2360      8456046 : pure subroutine sort_4tetra_int(list)
    2361              : 
    2362              :  integer, intent(inout) :: list(4)
    2363              : 
    2364              : !Local variables-------------------------------
    2365              :  integer :: va,vb,vc,vd, vlow1,vlow2,vhigh1,vhigh2
    2366              :  integer :: vlowest,vhighest, vmiddle1,vmiddle2
    2367              : 
    2368      8456046 :  va = list(1)
    2369      8456046 :  vb = list(2)
    2370      8456046 :  vc = list(3)
    2371      8456046 :  vd = list(4)
    2372              : 
    2373      8456046 :  if (va < vb) then
    2374              :      vlow1 = va; vhigh1 = vb
    2375              :  else
    2376      4340218 :      vlow1 = vb; vhigh1 = va
    2377              :  endif
    2378              : 
    2379      8456046 :  if (vc < vd) then
    2380              :      vlow2 = vc; vhigh2 = vd
    2381              :  else
    2382      4257565 :      vlow2 = vd; vhigh2 = vc
    2383              :  endif
    2384              : 
    2385      8456046 :  if (vlow1 < vlow2) then
    2386              :      vlowest  = vlow1; vmiddle1 = vlow2
    2387              :  else
    2388      4421792 :      vlowest  = vlow2; vmiddle1 = vlow1
    2389              :  endif
    2390              : 
    2391      8456046 :  if (vhigh1 > vhigh2) then
    2392              :      vhighest = vhigh1; vmiddle2 = vhigh2
    2393              :  else
    2394      4589119 :      vhighest = vhigh2; vmiddle2 = vhigh1
    2395              :  endif
    2396              : 
    2397      8456046 :  if (vmiddle1 < vmiddle2) then
    2398     24813400 :      list = [vlowest, vmiddle1, vmiddle2, vhighest]
    2399              :  else
    2400     17466830 :      list = [vlowest, vmiddle2, vmiddle1, vhighest]
    2401              :  endif
    2402              : 
    2403      8456046 : end subroutine sort_4tetra_int
    2404              : !!***
    2405              : 
    2406              : !!****f* m_htetra/get_onetetra_ppart_lv
    2407              : !! NAME
    2408              : !! get_onetetra_ppart_lv
    2409              : !!
    2410              : !! FUNCTION
    2411              : !!  Compute the complex weights according to: P. Lambin and J.P. Vigneron, Phys. Rev. B 29, 3430 (1984)
    2412              : !!
    2413              : !! INPUTS
    2414              : !!  nw
    2415              : !!  wvals: energy to evaluate the weights at
    2416              : !!  eig: eigenvalues at the corners of the tetrahedron
    2417              : !!
    2418              : !! OUTPUT
    2419              : !!  rwg(nw, 4)
    2420              : !!
    2421              : !! SOURCE
    2422              : 
    2423            0 : pure subroutine get_onetetra_ppart_lv(nw, wvals, eig, rwg)
    2424              : 
    2425              :  integer,intent(in) :: nw
    2426              :  real(dp), intent(in) :: wvals(nw), eig(4)
    2427              :  real(dp), intent(out) :: rwg(nw, 4)
    2428              : 
    2429              : !Local variables-------------------------------
    2430              :  integer :: ii, iw !jj,
    2431              :  real(dp),parameter :: tol = tol14
    2432              :  !real(dp),parameter :: tol = tol20
    2433              :  !real(dp),parameter :: tol = tol30
    2434              :  real(dp) :: D12,D13,D14,D23,D24,D34
    2435              :  real(dp) :: e10, e20, e30, e31, e32, e21
    2436              :  real(dp) :: inv_e10, inv_e21, inv_e20, inv_e30, inv_e31, inv_e32
    2437            0 :  real(dp) :: E0(nw), E1(nw), E2(nw), E3(nw)
    2438              : ! *********************************************************************
    2439              : 
    2440              :  ! Then the energy differences, for the coefficients. Must always be positive, I hope.
    2441            0 :  D12 = eig(2) - eig(1)
    2442            0 :  D13 = eig(3) - eig(1)
    2443            0 :  D14 = eig(4) - eig(1)
    2444            0 :  D23 = eig(3) - eig(2)
    2445            0 :  D24 = eig(4) - eig(2)
    2446            0 :  D34 = eig(4) - eig(3)
    2447              : 
    2448              :  ! Now get the actual weights
    2449              :  ! Notations
    2450              :  !  eij = e_i - e_j
    2451              :  !  Ej = E - e_j
    2452              : 
    2453            0 :  e10 = huge(one);  e20 = huge(one);  e30 = huge(one);
    2454            0 :  e31 = huge(one);  e32 = huge(one);  e21 = huge(one)
    2455            0 :  inv_e10 = huge(one);  inv_e21 = huge(one);  inv_e20 = huge(one)
    2456            0 :  inv_e30 = huge(one);  inv_e31 = huge(one);  inv_e32 = huge(one)
    2457              : 
    2458            0 :  E0 = wvals(:) - eig(1)
    2459            0 :  E1 = wvals(:) - eig(2)
    2460            0 :  E2 = wvals(:) - eig(3)
    2461            0 :  E3 = wvals(:) - eig(4)
    2462              : 
    2463              : #if 0
    2464              :  where (abs(E0) < tol1)
    2465              :    E0 = tol1
    2466              :  end where
    2467              :  where (abs(E1) < tol1)
    2468              :    E1 = tol1
    2469              :  end where
    2470              :  where (abs(E2) < tol1)
    2471              :    E2 = tol1
    2472              :  end where
    2473              :  where (abs(E3) < tol1)
    2474              :    E3 = tol1
    2475              :  end where
    2476              : #endif
    2477              : 
    2478              :  ! e1=e2=e3=e4
    2479            0 :  if (D12 + D23 + D34 < tol) then
    2480            0 :    do ii=1,4
    2481              :      !rwg(:, ii) = 0.25_dp / (wvals - eig(ii))
    2482            0 :      rwg(:, ii) = 0.25_dp / E0
    2483              :    end do
    2484              : 
    2485              :  ! e2=e3=e4
    2486            0 :  else if (D23 + D34 < tol) then
    2487            0 :    e10 = eig(2) - eig(1); inv_e10 = one / e10
    2488              : 
    2489            0 :    do iw=1,nw
    2490              :      rwg(iw, 1) = &
    2491              :        three * E0(iw)**2 * E1(iw) * inv_e10**4 * log(abs(E1(iw) / E0(iw))) &
    2492            0 :        + 1.5_dp * E1(iw) * (two * E0(iw) + e10) * inv_e10**3 + inv_e10
    2493              :    end do
    2494              : 
    2495            0 :    do iw=1,nw
    2496              :      rwg(iw, 2) = &
    2497              :        E0(iw) ** 3 * inv_e10**4 * log(abs(E0(iw) / E1(iw))) &
    2498            0 :        - (six * E0(iw)**2 + three * E0(iw) * e10 + two * e10**2) * inv_e10**3 / six
    2499              :    end do
    2500            0 :    rwg(:,3) = rwg(:,2)
    2501            0 :    rwg(:,4) = rwg(:,2)
    2502              : 
    2503              :    !rwg = zero
    2504              : 
    2505              :  ! e1=e2=e3
    2506            0 :  else if (D12 + D23 < tol) then
    2507              : 
    2508            0 :    e30 = eig(4) - eig(1); inv_e30 = one / e30
    2509              : 
    2510            0 :    do iw=1,nw
    2511              :      rwg(iw, 1) = &
    2512              :        E3(iw)**3 * inv_e30**4 * log(abs(E3(iw) / E0(iw))) &
    2513            0 :        + (six * E3(iw)**2 - three * E3(iw) * e30 + two * e30**2) * inv_e30**3 / six
    2514              :    end do
    2515            0 :    rwg(:,2) = rwg(:,1)
    2516            0 :    rwg(:,3) = rwg(:,1)
    2517              : 
    2518            0 :    do iw=1,nw
    2519              :      rwg(iw, 4) = &
    2520              :        three * E0(iw) * E3(iw)**2 * inv_e30**4 * log(abs(E0(iw) / E3(iw))) &
    2521            0 :        - 1.5_dp * E0(iw) * (two * E3(iw) - e30) * inv_e30**3 - inv_e30
    2522              :    end do
    2523              : 
    2524              :    !rwg = zero
    2525              : 
    2526              :  ! e1=e2 < e3=e4
    2527            0 :  else if (D12 + D34 < tol) then
    2528              : 
    2529            0 :    e20 = eig(3) - eig(1); inv_e20 = one / e20
    2530              : 
    2531            0 :    do iw=1,nw
    2532              :      rwg(iw, 1) = &
    2533              :        three * E0(iw) * E2(iw)**2 * inv_e20**4 * log(abs(E0(iw) / E2(iw))) &
    2534            0 :        - 1.5_dp * E0(iw) * (two * E2(iw) - e20) * inv_e20**3 - inv_e20
    2535              :    end do
    2536            0 :    rwg(:,2) = rwg(:,1)
    2537              : 
    2538            0 :    do iw=1,nw
    2539              :      rwg(iw, 3) = &
    2540              :        three * E0(iw)** 2 * E2(iw) * inv_e20**4 * log(abs(E2(iw) / E0(iw))) &
    2541            0 :        + 1.5_dp * E2(iw) * (two * E0(iw) + e20) * inv_e20**3 + inv_e20
    2542              :    end do
    2543            0 :    rwg(:,4) = rwg(:,3)
    2544              : 
    2545              :    !rwg = zero
    2546              : 
    2547              :  ! e3=e4
    2548            0 :  else if (D34 < tol) then
    2549              : 
    2550            0 :    e10 = eig(2) - eig(1); inv_e10 = one / e10
    2551            0 :    e20 = eig(3) - eig(1); inv_e20 = one / e20
    2552            0 :    e21 = eig(3) - eig(2); inv_e21 = one / e21
    2553              : 
    2554            0 :    do iw=1,nw
    2555              :      rwg(iw, 1) = &
    2556              :        E0(iw)**2 * inv_e20**2 * inv_e10  &
    2557              :        * (one + (-two * E2(iw) * inv_e20 - E1(iw) * inv_e10) * log(abs(E0(iw)))) &
    2558              :        - E2(iw)**2 * inv_e20**2 * inv_e21 &
    2559              :        * (one + (two * E0(iw) * inv_e20 + E1(iw) * inv_e21) * log(abs(E2(iw)))) &
    2560            0 :        + E1(iw)**3 * inv_e10**2 * inv_e21**2 * log(abs(E1(iw)))
    2561              :    end do
    2562              : 
    2563            0 :    do iw=1,nw
    2564              :      rwg(iw, 2) = &
    2565              :        -E1(iw)**2 * inv_e21**2 * inv_e10  &
    2566              :        * (one + (-two * E2(iw) * inv_e21 + E0(iw) * inv_e10) * log(abs(E1(iw)))) &
    2567              :        - E2(iw)**2 * inv_e21**2 * inv_e20 &
    2568              :        * (one + (two * E1(iw) * inv_e21 + E0(iw) * inv_e20) * log(abs(E2(iw)))) &
    2569            0 :        + E0(iw)**3 * inv_e10**2 * inv_e20**2 * log(abs(E0(iw)))
    2570              :    end do
    2571              : 
    2572            0 :    do iw=1,nw
    2573              :      rwg(iw, 3) = &
    2574              :        +E0(iw)**3 * inv_e10 * inv_e20**3 * log(abs(E0(iw))) &
    2575              :        -E1(iw)**3 * inv_e10 * inv_e21**3 * log(abs(E1(iw))) &
    2576              :        +E2(iw) * inv_e20 * inv_e21 &
    2577              :        * (half + E0(iw) * inv_e20 + E1(iw) * inv_e21  &
    2578              :          +(E0(iw)**2 * inv_e20**2 + E1(iw)**2 * inv_e21**2 + &
    2579            0 :            E0(iw) * E1(iw) * inv_e20 * inv_e21) * log(abs(E2(iw))))
    2580              :    end do
    2581              : 
    2582            0 :    rwg(:,4) = rwg(:,3)
    2583              : 
    2584              :    !rwg = zero
    2585              : 
    2586              :  ! e2=e3
    2587            0 :  else if (D23 < tol) then
    2588              : 
    2589            0 :    e10 = eig(2) - eig(1); inv_e10 = one / e10
    2590            0 :    e30 = eig(4) - eig(1); inv_e30 = one / e30
    2591            0 :    e31 = eig(4) - eig(2); inv_e31 = one / e31
    2592              : 
    2593            0 :    do iw=1,nw
    2594              :      rwg(iw, 1) = &
    2595              :        E0(iw)**2 * inv_e10**2 * inv_e30 &
    2596              :        * (one - (two * E1(iw) * inv_e10 + E3(iw) * inv_e30) * log(abs(E0(iw)))) &
    2597              :        + E1(iw)**2 * inv_e10**2 * inv_e31 &
    2598              :        * (one + (+two * E0(iw) * inv_e10 - E3(iw) * inv_e31) * log(abs(E1(iw)))) &
    2599            0 :        + E3(iw)**3 * inv_e30**2 * inv_e31**2 * log(abs(E3(iw)))
    2600              :    end do
    2601              : 
    2602            0 :    do iw=1,nw
    2603              :      rwg(iw, 2) = &
    2604              :         E0(iw)**3 * inv_e30 * inv_e10**3 * log(abs(E0(iw))) &
    2605              :        + E3(iw)**3 * inv_e30 * inv_e31**3 * log(abs(E3(iw))) &
    2606              :        - E1(iw) * inv_e10 * inv_e31  &
    2607              :        * (half + E0(iw) * inv_e10 - E3(iw) * inv_e31 + &
    2608            0 :          (E0(iw)**2 * inv_e10**2 + E3(iw)**2 * inv_e31**2 - E0(iw) * E3(iw) * inv_e10 * inv_e31) * log(abs(E1(iw))))
    2609              :    end do
    2610            0 :    rwg(:,3) = rwg(:,2)
    2611              : 
    2612            0 :    do iw=1,nw
    2613              :      rwg(iw, 4) = &
    2614              :        -E3(iw)**2 * inv_e31**2 * inv_e30 &
    2615              :        * (one + (two * E1(iw) * inv_e31 + E0(iw) * inv_e30) * log(abs(E3(iw)))) &
    2616              :        - E1(iw)**2 * inv_e31**2 * inv_e10 &
    2617              :        * (one + (-two * E3(iw) * inv_e31 + E0(iw) * inv_e10) * log(abs(E1(iw)))) &
    2618            0 :        + E0(iw)**3 * inv_e30**2 * inv_e10**2 * log(abs(E0(iw)))
    2619              :    end do
    2620              : 
    2621              :    !rwg = zero
    2622              : 
    2623              :  ! e1=e2
    2624            0 :  else if (D12 < tol) then
    2625              : 
    2626            0 :    e20 = eig(3) - eig(1); inv_e20 = one / e20
    2627            0 :    e30 = eig(4) - eig(1); inv_e30 = one / e30
    2628            0 :    e32 = eig(4) - eig(3); inv_e32 = one / e32
    2629              : 
    2630            0 :    do iw=1,nw
    2631              :      rwg(iw, 1) = &
    2632              :         -E2(iw)**3 * inv_e32 * inv_e20**3 * log(abs(E2(iw))) &
    2633              :        + E3(iw)**3 * inv_e32 * inv_e30**3 * log(abs(E3(iw))) &
    2634              :        + E0(iw) * inv_e20 * inv_e30  &
    2635              :        * (half - E2(iw) * inv_e20 - E3(iw) * inv_e30 + &
    2636            0 :          (E2(iw)**2 * inv_e20**2 + E3(iw)**2 * inv_e30**2 + E2(iw) * E3(iw) * inv_e20 * inv_e30) * log(abs(E0(iw))))
    2637              :    end do
    2638            0 :    rwg(:,2) = rwg(:,1)
    2639              : 
    2640            0 :    do iw=1,nw
    2641              :      rwg(iw, 3) = &
    2642              :         E2(iw)**2 * inv_e20**2 * inv_e32 &
    2643              :         * (one + (two * E0(iw) * inv_e20 - E3(iw) * inv_e32) * log(abs(E2(iw)))) &
    2644              :         + E0(iw)**2 * inv_e20**2 * inv_e30 &
    2645              :         * (one - (two * E2(iw) * inv_e20 + E3(iw) * inv_e30) * log(abs(E0(iw))))  &
    2646            0 :         + (E3(iw)**3 * inv_e32**2 * inv_e30**2 * log(abs(E3(iw))))
    2647              :    end do
    2648              :    ! This was wrong due to a misplaced parantes
    2649              :    !rwg(:,3) = zero
    2650              : 
    2651            0 :    do iw=1,nw
    2652              :      rwg(iw, 4) = &
    2653              :        -E3(iw)**2 * inv_e30**2 * inv_e32 &
    2654              :        * (one + (two * E0(iw) * inv_e30 + E2(iw) * inv_e32) * log(abs(E3(iw)))) &
    2655              :        + E0(iw)**2 * inv_e30**2 * inv_e20 &
    2656              :        * (one - (two * E3(iw) * inv_e30 + E2(iw) * inv_e20) * log(abs(E0(iw)))) &
    2657            0 :        + (E2(iw)**3 * inv_e32**2 * inv_e20**2 * log(abs(E2(iw))))
    2658              :    end do
    2659              : 
    2660              :    !rwg = zero
    2661              : 
    2662              :  ! e1<e2<e3<e4
    2663              :  else
    2664              : 
    2665            0 :    e10 = eig(2) - eig(1); inv_e10 = one / e10
    2666            0 :    e20 = eig(3) - eig(1); inv_e20 = one / e20
    2667            0 :    e21 = eig(3) - eig(2); inv_e21 = one / e21
    2668            0 :    e30 = eig(4) - eig(1); inv_e30 = one / e30
    2669            0 :    e31 = eig(4) - eig(2); inv_e31 = one / e31
    2670            0 :    e32 = eig(4) - eig(3); inv_e32 = one / e32
    2671              : 
    2672            0 :    do iw=1,nw
    2673              :      rwg(iw, 1) = &
    2674              :        E0(iw)**2 * inv_e10 * inv_e20 * inv_e30 &
    2675              :        * (one - (E1(iw) * inv_e10 + E2(iw) * inv_e20 + E3(iw) * inv_e30) * log(abs(E0(iw)))) &
    2676              :        + E1(iw)**3 * inv_e10**2 * inv_e21 * inv_e31 * log(abs(E1(iw))) &
    2677              :        - E2(iw)**3 * inv_e20**2 * inv_e21 * inv_e32 * log(abs(E2(iw))) &
    2678            0 :        + E3(iw)**3 * inv_e30**2 * inv_e31 * inv_e32 * log(abs(E3(iw)))
    2679              :    end do
    2680              : 
    2681            0 :    do iw=1,nw
    2682              :      rwg(iw, 2) = &
    2683              :        -E1(iw)**2 * inv_e10 * inv_e21 * inv_e31 &
    2684              :        * (one + (E0(iw) * inv_e10 - E2(iw) * inv_e21 - E3(iw) * inv_e31) * log(abs(E1(iw)))) &
    2685              :        + E0(iw)**3 * inv_e10**2 * inv_e20 * inv_e30 * log(abs(E0(iw))) &
    2686              :        - E2(iw)**3 * inv_e20 * inv_e21**2 * inv_e32 * log(abs(E2(iw))) &
    2687            0 :        + E3(iw)**3 * inv_e30 * inv_e31**2 * inv_e32 * log(abs(E3(iw)))
    2688              :    end do
    2689              : 
    2690            0 :    do iw=1,nw
    2691              :      rwg(iw, 3) = &
    2692              :        E2(iw)**2 * inv_e20 * inv_e21 * inv_e32 &
    2693              :        * (one + (E0(iw) * inv_e20 + E1(iw) * inv_e21 - E3(iw) * inv_e32) * log(abs(E2(iw)))) &
    2694              :        + E0(iw)**3 * inv_e10 * inv_e20**2 * inv_e30 * log(abs(E0(iw))) &
    2695              :        - E1(iw)**3 * inv_e10 * inv_e21**2 * inv_e31 * log(abs(E1(iw))) &
    2696            0 :        + E3(iw)**3 * inv_e30 * inv_e31 * inv_e32**2 * log(abs(E3(iw)))
    2697              :    end do
    2698              : 
    2699            0 :    do iw=1,nw
    2700              :      rwg(iw, 4) = &
    2701              :        -E3(iw)**2 * inv_e30 * inv_e31 * inv_e32 &
    2702              :        * (one + (E0(iw) * inv_e30 + E1(iw) * inv_e31 + E2(iw) * inv_e32) * log(abs(E3(iw)))) &
    2703              :        + E0(iw)**3 * inv_e10 * inv_e20 * inv_e30**2 * log(abs(E0(iw))) &
    2704              :        - E1(iw)**3 * inv_e10 * inv_e21 * inv_e31**2 * log(abs(E1(iw))) &
    2705            0 :        + E2(iw)**3 * inv_e20 * inv_e21 * inv_e32**2 * log(abs(E2(iw)))
    2706              :    end do
    2707              :    !rwg = zero
    2708              : 
    2709              :  end if
    2710              : 
    2711            0 : end subroutine get_onetetra_ppart_lv
    2712              : !!***
    2713              : 
    2714          729 : end module m_htetra
    2715              : !!***
        

Generated by: LCOV version 2.3-1