TABLE OF CONTENTS


ABINIT/m_tetrahedron [ Modules ]

[ Top ] [ Modules ]

NAME

 m_tetrahedron

FUNCTION

  module for tetrahedron interpolation of DOS and similar quantities
  depends on sort_tetra and on m_kpt_rank

COPYRIGHT

  Copyright (C) 2010-2024 ABINIT group (MJV)
  This file is distributed under the terms of the
  GNU General Public License, see ~abinit/COPYING
  or http://www.gnu.org/copyleft/gpl.txt .

TODO

  1) Test carefully the case of degenerate tetrahedron
  2) Change API so that we can pass the energy mesh instead of omega_min and omega_max
  3) Add table ik_ibz --> tetra_list to avoid cycling inside big loop over ntetra
  4) Add options to get only delta and/or theta ?

SOURCE

23 #if defined HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include "libtetra.h"
28 
29 module m_tetrahedron
30 
31   ! make sure stdout is defined, as libtetra.h needs it
32  use, intrinsic :: iso_fortran_env, only : stdin=>input_unit, &
33                                           stdout=>output_unit, &
34                                           stderr=>error_unit
35  USE_MEMORY_PROFILING
36  USE_MSG_HANDLING
37  use m_krank
38 #ifdef HAVE_MPI2
39  use mpi
40 #endif
41 #ifdef HAVE_LIBTETRA_ABINIT
42  use m_io_tools, only : open_file
43  use m_xmpi
44 #endif
45 
46 implicit none
47 
48 #if defined HAVE_MPI1
49  include 'mpif.h'
50 #endif
51 
52 private

m_tetrahedron/destroy_tetra [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

 destroy_tetra

FUNCTION

 deallocate tetrahedra pointers if needed

SOURCE

134 subroutine destroy_tetra (tetra)
135 
136  type(t_tetrahedron), intent(inout) :: tetra
137 
138  if (allocated(tetra%tetra_full)) then
139    TETRA_DEALLOCATE(tetra%tetra_full)
140  end if
141  if (allocated(tetra%tetra_mult)) then
142    TETRA_DEALLOCATE(tetra%tetra_mult)
143  end if
144  if (allocated(tetra%tetra_wrap)) then
145    TETRA_DEALLOCATE(tetra%tetra_wrap)
146  end if
147  if (allocated(tetra%ibz_tetra_count)) then
148    TETRA_DEALLOCATE(tetra%ibz_tetra_count)
149  end if
150  if (allocated(tetra%ibz_tetra_mapping)) then
151    TETRA_DEALLOCATE(tetra%ibz_tetra_mapping)
152  end if
153 
154 end subroutine destroy_tetra

m_tetrahedron/get_dbl_tetra_weight [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

 get_dbl_tetra_weight

FUNCTION

 calculate integration weights and their derivatives
 for double tetrahedron method from Allen Phys Stat Sol B 120 529 (1983) [[cite:Allen1983b]]
 the k-points and tetrahedra must be the same for both grids, of course,
 but the range of energies is arbitrary

 Omega is called eigen1 here
 E is called eigen2 here
 indexing goes from 1 to 4 for the tetrahedron corners, in order of increasing eigen1
  in Allen, from 0 to 3...

INPUTS

 eigen1_in(nkpt)=eigenenergies for each k point
 eigen2_in(nkpt)=eigenenergies for each k point
 enemin1=minimal energy for DOS in energy 1
 enemax1=maximal energy for DOS
 enemin2=minimal energy for DOS in energy 2
 enemax2=maximal energy for DOS
 max_occ=maximal occupation number (2 for nsppol=1, 1 for nsppol=2)
 nene1=number of energies for DOS in energy 1
 nene2=number of energies for DOS in energy 2
 nkpt=number of irreducible kpoints
 tetra%ntetra=number of tetra
 tetra%tetra_full(4,2,ntetra)=for each irred tetrahedron, the list of k point vertices
   1 -> irred kpoint   2 -> fullkpt
 tetra%tetra_mult(ntetra)=for each irred tetrahedron, its multiplicity
 tetra%vv = ratio of volume of one tetrahedron in reciprocal space to full BZ volume
 ierr = error code on exit

OUTPUT

  tweight(nkpt,nene1,nene2) = integration weights for each irred kpoint from all adjacent tetrahedra
  dtweightde(nkpt,nene1,nene2) = derivative of tweight wrt energy

SOURCE

 809 subroutine get_dbl_tetra_weight(eigen1_in,eigen2_in,enemin1,enemax1,enemin2,enemax2,&
 810 &    max_occ,nene1,nene2,nkpt,tetra,tweight,dtweightde, ierr)
 811 
 812 !Arguments ------------------------------------
 813 !scalars
 814  integer,intent(in) :: nene1,nene2,nkpt
 815  integer,intent(out) :: ierr
 816  type(t_tetrahedron), intent(in) :: tetra
 817  real(dp),intent(in) :: enemax1,enemin1
 818  real(dp),intent(in) :: enemax2,enemin2
 819  real(dp),intent(in) :: max_occ
 820 !arrays
 821  real(dp),intent(in) :: eigen1_in(nkpt)
 822  real(dp),intent(in) :: eigen2_in(nkpt)
 823  real(dp),intent(out) :: dtweightde(nkpt,nene1,nene2),tweight(nkpt,nene1,nene2)
 824 
 825 !Local variables-------------------------------
 826 !  needed for gaussian replacement of Dirac functions
 827 !  the three coefficients of the DOS as quadratic form,
 828 !    in the interval [eig(ikpt-1), eig(ikpt)]
 829 !    for ikpt = 1 we add a point below eigen(1) which doesnt
 830 !    contribute to the DOS in any tetrahedron
 831 !scalars
 832  integer :: ieps1,ieps2,itetra
 833  integer :: nn1_1,nn1_2,nn1_3,nn1_4
 834  integer :: nn2_1,nn2_2,nn2_3
 835  integer :: ind_a(3), ind_b(3), ind_c(3)
 836  real(dp)  :: deltaene1,eps1
 837  real(dp)  :: deltaene2,eps2
 838 ! real(dp)  :: gau_prefactor,gau_width,gau_width2
 839  real(dp)  :: epsilon1(4,4)
 840  real(dp)  :: epsilon2(4,4)
 841  real(dp)  :: inv_epsilon1(4,4)
 842  real(dp)  :: aa(3),bb(3),cc(3)
 843  real(dp)  :: delaa(3),delbb(3),delcc(3)
 844  real(dp)  :: delaa0,delbb0,delcc0
 845  real(dp)  :: inv_delaa(3),inv_delbb(3),inv_delcc(3)
 846  real(dp)  :: deleps1, deleps2
 847  real(dp)  :: inv_deleps1
 848  real(dp)  :: dccde1, dccde1_pre
 849  real(dp)  :: volconst,volconst_mult
 850  real(dp)  :: ii0, ii1, ii3
 851 !arrays
 852  integer :: ind_k(4)
 853  real(dp), allocatable :: tweight_tmp(:,:,:)
 854  real(dp), allocatable :: dtweightde_tmp(:,:,:)
 855  real(dp)  :: eigen1_1tetra(4)
 856  real(dp)  :: eigen2_1tetra(4)
 857 
 858 ! *********************************************************************
 859 
 860  ierr = 0
 861  if (nene1 <= 1 .or. nene2 <= 1)  then
 862    !'get_dbl_tetra_weight: nene must be at least 2'
 863    ierr = 1
 864    return
 865  else
 866    deltaene1 = (enemax1-enemin1) / (nene1-1)
 867    deltaene2 = (enemax2-enemin2) / (nene2-1)
 868  end if
 869 
 870  TETRA_ALLOCATE(tweight_tmp, (4, nene2, nene1))
 871  TETRA_ALLOCATE(dtweightde_tmp, (4, nene2, nene1))
 872 
 873 !print *, "warning: for the moment, heaviside weights are 0. The delta function / DOS weights are the only ones calculated "
 874 
 875  volconst = tetra%vv/4.d0
 876 
 877  ! for each tetrahedron
 878  do itetra=1,tetra%ntetra
 879    ! these are for 1 tetrahedron only.
 880    tweight_tmp = zero
 881    dtweightde_tmp = zero
 882 
 883    volconst_mult = max_occ*volconst*dble(tetra%tetra_mult(itetra))
 884 
 885    ! Here we need the original ordering to reference the correct irred kpoints
 886    ! ind_k refers to the index in the full k list of the summits of the present tetrahedra
 887    ! we can forget the order of the summits within the tetrahedron, because eigen1 fixes that
 888    ! order with its increasing value
 889    ind_k(1) = tetra%tetra_full(1,1,itetra)
 890    ind_k(2) = tetra%tetra_full(2,1,itetra)
 891    ind_k(3) = tetra%tetra_full(3,1,itetra)
 892    ind_k(4) = tetra%tetra_full(4,1,itetra)
 893    eigen1_1tetra(1) = eigen1_in(ind_k(1))
 894    eigen1_1tetra(2) = eigen1_in(ind_k(2))
 895    eigen1_1tetra(3) = eigen1_in(ind_k(3))
 896    eigen1_1tetra(4) = eigen1_in(ind_k(4))
 897    call sort_tetra(4,eigen1_1tetra,ind_k,tol14)
 898 
 899    ! re-sort eigen2 values according to order chosen for eigen1. Eigen2 are _not_ in increasing order!
 900    eigen2_1tetra(1) = eigen2_in(ind_k(1))
 901    eigen2_1tetra(2) = eigen2_in(ind_k(2))
 902    eigen2_1tetra(3) = eigen2_in(ind_k(3))
 903    eigen2_1tetra(4) = eigen2_in(ind_k(4))
 904 
 905    ! the epsilons are energy differences for the two eigenvalue sets
 906    epsilon1 = zero
 907    epsilon2 = zero
 908    do ieps1 = 1, 4
 909      do ieps2 = ieps1+1, 4
 910        epsilon1(ieps1,ieps2) = eigen1_1tetra(ieps1)-eigen1_1tetra(ieps2)
 911        epsilon1(ieps2,ieps1) = -epsilon1(ieps1,ieps2)
 912        epsilon2(ieps1,ieps2) = eigen2_1tetra(ieps1)-eigen2_1tetra(ieps2)
 913        epsilon2(ieps2,ieps1) = -epsilon2(ieps1,ieps2)
 914      end do
 915    end do
 916 
 917    ! we precalculate the inverses to avoid doing tons of divisions in the energy loops below
 918    ! Allen formulae only require the inverses of the differences of eigen1 + the a b c below
 919    inv_epsilon1 = zero
 920    do ieps1 = 1, 4
 921      do ieps2 = ieps1+1, 4
 922        if (abs(epsilon1(ieps1,ieps2)) > tol6) then
 923          inv_epsilon1(ieps1,ieps2) = 1.d0 / epsilon1(ieps1,ieps2)
 924          inv_epsilon1(ieps2,ieps1) = -inv_epsilon1(ieps1,ieps2)
 925        end if
 926      end do
 927    end do
 928 
 929    ! these bounds determine the intervals for Omega in Allen paper, and cases A, B, C
 930    nn1_1 = int((eigen1_1tetra(1)-enemin1)/deltaene1)+1
 931    nn1_2 = int((eigen1_1tetra(2)-enemin1)/deltaene1)+1
 932    nn1_3 = int((eigen1_1tetra(3)-enemin1)/deltaene1)+1
 933    nn1_4 = int((eigen1_1tetra(4)-enemin1)/deltaene1)+1
 934 
 935    nn1_1 = max(1,nn1_1)
 936    nn1_1 = min(nn1_1,nene1)
 937    nn1_2 = max(1,nn1_2)
 938    nn1_2 = min(nn1_2,nene1)
 939    nn1_3 = max(1,nn1_3)
 940    nn1_3 = min(nn1_3,nene1)
 941    nn1_4 = max(1,nn1_4)
 942    nn1_4 = min(nn1_4,nene1)
 943 
 944    ! calculate Allen a_i b_i and c_i parameters
 945    ! sort the a_i b_i c_i
 946    !
 947    ! NOTE: indices here go from 1 to 4 instead of 0 to 3 as in Allen...
 948    aa(1) = epsilon2(2,1) * inv_epsilon1(2,1)
 949    aa(2) = epsilon2(3,1) * inv_epsilon1(3,1)
 950    aa(3) = epsilon2(4,1) * inv_epsilon1(4,1)
 951    ind_a = (/2,3,4/)
 952    call sort_tetra(3,aa,ind_a,tol14)
 953    ! aa are now in order a_s a_m a_l !!! Preserve the hash function ind_a to order the positions of k below
 954    delaa(1) = aa(2)-aa(1)
 955    delaa(2) = aa(3)-aa(1)
 956    delaa(3) = aa(3)-aa(2)
 957    inv_delaa = zero
 958    if(delaa(1)> tol6) inv_delaa(1)= 1.0d0 / delaa(1)
 959    if(delaa(2)> tol6) inv_delaa(2)= 1.0d0 / delaa(2)
 960    if(delaa(3)> tol6) inv_delaa(3)= 1.0d0 / delaa(3)
 961 
 962    bb(1) = epsilon2(1,2) * inv_epsilon1(1,2)
 963    bb(2) = epsilon2(3,2) * inv_epsilon1(3,2)
 964    bb(3) = epsilon2(4,2) * inv_epsilon1(4,2)
 965    ind_b = (/1,3,4/)
 966    call sort_tetra(3,bb,ind_b,tol14)
 967    delbb(1) = bb(2)-bb(1)
 968    delbb(2) = bb(3)-bb(1)
 969    delbb(3) = bb(3)-bb(2)
 970    inv_delbb = zero
 971    if(delbb(1)> tol6) inv_delbb(1)= 1.0d0 / delbb(1)
 972    if(delbb(2)> tol6) inv_delbb(2)= 1.0d0 / delbb(2)
 973    if(delbb(3)> tol6) inv_delbb(3)= 1.0d0 / delbb(3)
 974 
 975    cc(1) = epsilon2(1,4) * inv_epsilon1(1,4)
 976    cc(2) = epsilon2(2,4) * inv_epsilon1(2,4)
 977    cc(3) = epsilon2(3,4) * inv_epsilon1(3,4)
 978    ind_c = (/1,2,3/)
 979    call sort_tetra(3,cc,ind_c,tol14)
 980    delcc(1) = cc(2)-cc(1)
 981    delcc(2) = cc(3)-cc(1)
 982    delcc(3) = cc(3)-cc(2)
 983    inv_delcc = zero
 984    if(delcc(1)> tol6) inv_delcc(1)= 1.0d0 / delcc(1)
 985    if(delcc(2)> tol6) inv_delcc(2)= 1.0d0 / delcc(2)
 986    if(delcc(3)> tol6) inv_delcc(3)= 1.0d0 / delcc(3)
 987 
 988    !----------------------------------------------------------------------
 989    ! start main loop A B C over eps1
 990    !----------------------------------------------------------------------
 991 
 992    !
 993    !  interval enemin1 < eps1 < e1 nothing to do
 994    !
 995    !
 996    !  interval e1 < eps1 < e3   CASE A in Allen + first term in B
 997    !
 998    ! NB: eps1 is not updated inside the loop, only between the loops
 999    eps1 = enemin1+nn1_1*deltaene1
1000    deleps1 = eps1-eigen1_1tetra(1) ! this is Omega - omega_0
1001    dccde1_pre = 6.d0*volconst_mult*inv_epsilon1(2,1)*inv_epsilon1(3,1)*inv_epsilon1(4,1)
1002 
1003    ! note we go to nn1_3
1004    do ieps1=nn1_1+1,nn1_3
1005 
1006      dccde1 = dccde1_pre * deleps1  ! this is f_0(Omega)*6*v
1007 
1008      ! at fixed ieps1 we can find the pivot indices for the ieps2 loop
1009      nn2_1 = int((eigen2_1tetra(1)+deleps1*aa(1) -enemin2)/deltaene2)+1
1010      nn2_2 = int((eigen2_1tetra(1)+deleps1*aa(2) -enemin2)/deltaene2)+1
1011      nn2_3 = int((eigen2_1tetra(1)+deleps1*aa(3) -enemin2)/deltaene2)+1
1012 
1013      nn2_1 = max(1,nn2_1)
1014      nn2_1 = min(nn2_1,nene2)
1015      nn2_2 = max(1,nn2_2)
1016      nn2_2 = min(nn2_2,nene2)
1017      nn2_3 = max(1,nn2_3)
1018      nn2_3 = min(nn2_3,nene2)
1019 
1020      inv_deleps1 = 1.0d0 / deleps1
1021 
1022      eps2 = enemin2+nn2_1*deltaene2 ! this is E
1023      deleps2 = eps2 - eigen2_1tetra(1) ! this is E-epsilon_0
1024 
1025      !-----------------------------------------------------------------------
1026      ! This is case AI
1027      !-----------------------------------------------------------------------
1028      do ieps2 = nn2_1+1, nn2_2
1029        ! calculate running value of del "a"  = a-a_s: first term should really mix eps1 and eps2
1030        delaa0 = deleps2*inv_deleps1 - aa(1) ! a - a_s
1031 
1032        ii0 = dccde1*delaa0*inv_delaa(1)*inv_delaa(2) ! this is I_0(Omega E)
1033 
1034        dtweightde_tmp(1,ieps2,ieps1) = dtweightde_tmp(1,ieps2,ieps1) + &
1035 &         ii0*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_a(1),1)* &
1036 &                 (-2.0d0 + delaa0*inv_delaa(1)*epsilon1(ind_a(2),ind_a(1))*inv_epsilon1(ind_a(2),1) &
1037 &                         + delaa0*inv_delaa(2)*epsilon1(ind_a(3),ind_a(1))*inv_epsilon1(ind_a(3),1)))
1038        dtweightde_tmp(ind_a(1),ieps2,ieps1) = dtweightde_tmp(ind_a(1),ieps2,ieps1) + &
1039 &         ii0*0.5d0*deleps1*inv_epsilon1(ind_a(1),1)*(2.0d0 - delaa0*inv_delaa(1) - delaa0*inv_delaa(2))
1040        dtweightde_tmp(ind_a(2),ieps2,ieps1) = dtweightde_tmp(ind_a(2),ieps2,ieps1) + &
1041 &         ii0*0.5d0*delaa0*inv_delaa(1)*deleps1*inv_epsilon1(ind_a(2),1)
1042        dtweightde_tmp(ind_a(3),ieps2,ieps1) = dtweightde_tmp(ind_a(3),ieps2,ieps1) + &
1043 &         ii0*0.5d0*delaa0*inv_delaa(2)*deleps1*inv_epsilon1(ind_a(3),1)
1044        deleps2 = deleps2 + deltaene2
1045      end do
1046 
1047 
1048      eps2 = enemin2+nn2_2*deltaene2 ! this is E
1049      deleps2 = eps2 - eigen2_1tetra(1)  ! E-E_0
1050 
1051      !-----------------------------------------------------------------------
1052      ! This is case AII
1053      !-----------------------------------------------------------------------
1054      do ieps2 = nn2_2+1, nn2_3
1055        ! calculate running value of del "a"  = a_l-a: first term should really mix eps1 and eps2
1056        delaa0 = aa(3) - deleps2*inv_deleps1 ! a_l - a
1057 
1058        ii0 = dccde1*delaa0*inv_delaa(3)*inv_delaa(2) ! this is I_0(Omega E)
1059 
1060        dtweightde_tmp(1,ieps2,ieps1) = dtweightde_tmp(1,ieps2,ieps1) + &
1061 &         ii0*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_a(3),1)* &
1062 &                 (-2.0d0 + delaa0*inv_delaa(3)*epsilon1(ind_a(2),ind_a(3))*inv_epsilon1(ind_a(2),1) &
1063 &                         + delaa0*inv_delaa(2)*epsilon1(ind_a(1),ind_a(3))*inv_epsilon1(ind_a(1),1)))
1064        dtweightde_tmp(ind_a(3),ieps2,ieps1) = dtweightde_tmp(ind_a(3),ieps2,ieps1) + &
1065 &         ii0*0.5d0*deleps1*inv_epsilon1(ind_a(3),1)*(2.0d0 - delaa0*inv_delaa(3) - delaa0*inv_delaa(2))
1066        dtweightde_tmp(ind_a(2),ieps2,ieps1) = dtweightde_tmp(ind_a(2),ieps2,ieps1) + &
1067 &         ii0*0.5d0*delaa0*inv_delaa(3)*deleps1*inv_epsilon1(ind_a(2),1)
1068        dtweightde_tmp(ind_a(1),ieps2,ieps1) = dtweightde_tmp(ind_a(1),ieps2,ieps1) + &
1069 &         ii0*0.5d0*delaa0*inv_delaa(2)*deleps1*inv_epsilon1(ind_a(1),1)
1070 
1071        deleps2 = deleps2 + deltaene2
1072      end do
1073      deleps1 = deleps1 + deltaene1
1074    end do
1075    !
1076    !  interval e2 < eps < e3
1077    !
1078    eps1 = eps1 + (nn1_2-nn1_1)*deltaene1
1079 
1080    deleps1 = eps1-eigen1_1tetra(2) ! Omega - omega_1
1081 
1082    dccde1_pre = 6.d0*volconst_mult*inv_epsilon1(2,1)*inv_epsilon1(3,2)*inv_epsilon1(4,2) ! f1 function
1083    do ieps1=nn1_2+1,nn1_3
1084 
1085      dccde1 = dccde1_pre * deleps1 ! f2(Omega) * 6 * v
1086 
1087      ! at fixed ieps1 we can find the pivot indices for the ieps2 loop
1088      nn2_1 = int((eigen2_1tetra(2)+deleps1*bb(1) -enemin2)/deltaene2)+1
1089      nn2_2 = int((eigen2_1tetra(2)+deleps1*bb(2) -enemin2)/deltaene2)+1
1090      nn2_3 = int((eigen2_1tetra(2)+deleps1*bb(3) -enemin2)/deltaene2)+1
1091 
1092      nn2_1 = max(1,nn2_1)
1093      nn2_1 = min(nn2_1,nene2)
1094      nn2_2 = max(1,nn2_2)
1095      nn2_2 = min(nn2_2,nene2)
1096      nn2_3 = max(1,nn2_3)
1097      nn2_3 = min(nn2_3,nene2)
1098 
1099      inv_deleps1 = 1.0d0 / deleps1
1100 
1101      eps2 = enemin2+nn2_1*deltaene2 ! starting value for E
1102      deleps2 = eps2 - eigen2_1tetra(2) ! E - epsilon_1
1103 
1104      !-----------------------------------------------------------------------
1105      ! This is case BI
1106      !-----------------------------------------------------------------------
1107      do ieps2 = nn2_1+1, nn2_2
1108        ! calculate running value of del "b"  = b-b_s: first term should really mix eps1 and eps2
1109        delbb0 = deleps2*inv_deleps1 - bb(1)
1110 
1111        ii1 = dccde1*delbb0*inv_delbb(1)*inv_delbb(2) ! this is I_1(Omega E)
1112 
1113        ! note negative sign here - we are correcting the I0 a0 term already calculated above
1114        dtweightde_tmp(2,ieps2,ieps1) = dtweightde_tmp(2,ieps2,ieps1) - &
1115 &         ii1*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_b(1),2)* &
1116 &                 (-2.0d0 + delbb0*inv_delbb(1)*epsilon1(ind_b(2),ind_b(1))*inv_epsilon1(ind_b(2),2) &
1117 &                         + delbb0*inv_delbb(2)*epsilon1(ind_b(3),ind_b(1))*inv_epsilon1(ind_b(3),2)))
1118        dtweightde_tmp(ind_b(1),ieps2,ieps1) = dtweightde_tmp(ind_b(1),ieps2,ieps1) - &
1119 &         ii1*0.5d0*deleps1*inv_epsilon1(ind_b(1),2)*(2.0d0 - delbb0*inv_delbb(1) - delbb0*inv_delbb(2))
1120        dtweightde_tmp(ind_b(2),ieps2,ieps1) = dtweightde_tmp(ind_b(2),ieps2,ieps1) - &
1121 &         ii1*0.5d0*delbb0*inv_delbb(1)*deleps1*inv_epsilon1(ind_b(2),2)
1122        dtweightde_tmp(ind_b(3),ieps2,ieps1) = dtweightde_tmp(ind_b(3),ieps2,ieps1) - &
1123 &         ii1*0.5d0*delbb0*inv_delbb(2)*deleps1*inv_epsilon1(ind_b(3),2)
1124        deleps2 = deleps2 + deltaene2
1125      end do
1126 
1127      eps2 = enemin2+nn2_2*deltaene2
1128      deleps2 = eps2 - eigen2_1tetra(2)
1129 
1130      !-----------------------------------------------------------------------
1131      ! This is case BII
1132      !-----------------------------------------------------------------------
1133      do ieps2 = nn2_2+1, nn2_3
1134        ! calculate running value of del "b"  = b_l-b: first term should really mix eps1 and eps2
1135        delbb0 = bb(3) - deleps2*inv_deleps1
1136 
1137        ii1 = dccde1*delbb0*inv_delbb(3)*inv_delbb(2) ! this is I_1(Omega E)
1138 
1139        ! note negative sign here - we are correcting the I0 a0 term already calculated above
1140        dtweightde_tmp(2,ieps2,ieps1) = dtweightde_tmp(2,ieps2,ieps1) - &
1141 &         ii1*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_b(3),2)* &
1142 &                 (-2.0d0 + delbb0*inv_delbb(3)*epsilon1(ind_b(2),ind_b(3))*inv_epsilon1(ind_b(2),2) &
1143 &                         + delbb0*inv_delbb(2)*epsilon1(ind_b(1),ind_b(3))*inv_epsilon1(ind_b(1),2)))
1144        dtweightde_tmp(ind_b(3),ieps2,ieps1) = dtweightde_tmp(ind_b(3),ieps2,ieps1) - &
1145 &         ii1*0.5d0*deleps1*inv_epsilon1(ind_b(3),2)*(2.0d0 - delbb0*inv_delbb(3) - delbb0*inv_delbb(2))
1146        dtweightde_tmp(ind_b(2),ieps2,ieps1) = dtweightde_tmp(ind_b(2),ieps2,ieps1) - &
1147 &         ii1*0.5d0*delbb0*inv_delbb(3)*deleps1*inv_epsilon1(ind_b(2),2)
1148        dtweightde_tmp(ind_b(1),ieps2,ieps1) = dtweightde_tmp(ind_b(1),ieps2,ieps1) - &
1149 &         ii1*0.5d0*delbb0*inv_delbb(2)*deleps1*inv_epsilon1(ind_b(1),2)
1150 
1151        deleps2 = deleps2 + deltaene2
1152      end do
1153 
1154      deleps1 = deleps1 + deltaene1
1155    end do
1156 
1157    !
1158    !  interval e3 < eps < e4
1159    !
1160    eps1 = eps1 + (nn1_3-nn1_2)*deltaene1
1161    deleps1 = eps1-eigen1_1tetra(4)
1162    dccde1_pre = 6.d0*volconst_mult*inv_epsilon1(4,1)*inv_epsilon1(4,2)*inv_epsilon1(4,3)
1163    do ieps1=nn1_3+1,nn1_4
1164      ! note - sign from definition of f3
1165      dccde1 = -dccde1_pre *  deleps1 ! f3(Omega) * 6 * v
1166 
1167      ! at fixed ieps1 we can find the pivot indices for the ieps2 loop
1168      ! NB: order is inverted for cc because deleps1 is defined negative (Omega is always less than omega_3)
1169      nn2_1 = int((eigen2_1tetra(4)+deleps1*cc(3) -enemin2)/deltaene2)+1
1170      nn2_2 = int((eigen2_1tetra(4)+deleps1*cc(2) -enemin2)/deltaene2)+1
1171      nn2_3 = int((eigen2_1tetra(4)+deleps1*cc(1) -enemin2)/deltaene2)+1
1172 
1173      nn2_1 = max(1,nn2_1)
1174      nn2_1 = min(nn2_1,nene2)
1175      nn2_2 = max(1,nn2_2)
1176      nn2_2 = min(nn2_2,nene2)
1177      nn2_3 = max(1,nn2_3)
1178      nn2_3 = min(nn2_3,nene2)
1179      inv_deleps1 = 1.0d0 / deleps1
1180 
1181      eps2 = enemin2+nn2_1*deltaene2 ! starting value for E
1182      deleps2 = eps2 - eigen2_1tetra(4) ! E - epsilon_3
1183 
1184      !-----------------------------------------------------------------------
1185      ! This is case CII
1186      !-----------------------------------------------------------------------
1187      do ieps2 = nn2_1+1, nn2_2
1188        ! calculate running value of del "c"  = c_l-c: first term should really mix eps1 and eps2
1189        delcc0 = cc(3) - deleps2*inv_deleps1
1190 
1191        ii3 = dccde1*delcc0*inv_delcc(3)*inv_delcc(2) ! this is I_3(Omega E)
1192 
1193        dtweightde_tmp(4,ieps2,ieps1) = dtweightde_tmp(4,ieps2,ieps1) + &
1194 &         ii3*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_c(3),4)* &
1195 &                 (-2.0d0 + delcc0*inv_delcc(3)*epsilon1(ind_c(2),ind_c(3))*inv_epsilon1(ind_c(2),4) &
1196 &                         + delcc0*inv_delcc(2)*epsilon1(ind_c(1),ind_c(3))*inv_epsilon1(ind_c(1),4)))
1197        dtweightde_tmp(ind_c(3),ieps2,ieps1) = dtweightde_tmp(ind_c(3),ieps2,ieps1) + &
1198 &         ii3*0.5d0*deleps1*inv_epsilon1(ind_c(3),4)*(2.0d0 - delcc0*inv_delcc(3) - delcc0*inv_delcc(2))
1199        dtweightde_tmp(ind_c(2),ieps2,ieps1) = dtweightde_tmp(ind_c(2),ieps2,ieps1) + &
1200 &         ii3*0.5d0*delcc0*inv_delcc(3)*deleps1*inv_epsilon1(ind_c(2),4)
1201        dtweightde_tmp(ind_c(1),ieps2,ieps1) = dtweightde_tmp(ind_c(1),ieps2,ieps1) + &
1202 &         ii3*0.5d0*delcc0*inv_delcc(2)*deleps1*inv_epsilon1(ind_c(1),4)
1203 
1204        deleps2 = deleps2 + deltaene2
1205      end do
1206 
1207 
1208      eps2 = enemin2+nn2_2*deltaene2
1209      deleps2 = eps2 - eigen2_1tetra(4)
1210 
1211      !-----------------------------------------------------------------------
1212      ! This is case CI
1213      !-----------------------------------------------------------------------
1214      do ieps2 = nn2_2+1, nn2_3
1215        ! calculate running value of del "c"  = c-c_s: first term should really mix eps1 and eps2
1216        delcc0 = deleps2*inv_deleps1 - cc(1) ! c - c_s
1217 
1218        ii3 = dccde1*delcc0*inv_delcc(1)*inv_delcc(2) ! this is I_3(Omega E)
1219 
1220        dtweightde_tmp(4,ieps2,ieps1) = dtweightde_tmp(4,ieps2,ieps1) + &
1221 &         ii3*(1.d0 + 0.5d0*deleps1*inv_epsilon1(ind_c(1),4)* &
1222 &                 (-2.0d0 + delcc0*inv_delcc(1)*epsilon1(ind_c(2),ind_c(1))*inv_epsilon1(ind_c(2),4) &
1223 &                         + delcc0*inv_delcc(2)*epsilon1(ind_c(3),ind_c(1))*inv_epsilon1(ind_c(3),4)))
1224        dtweightde_tmp(ind_c(1),ieps2,ieps1) = dtweightde_tmp(ind_c(1),ieps2,ieps1) + &
1225 &         ii3*0.5d0*deleps1*inv_epsilon1(ind_c(1),4)*(2.0d0 - delcc0*inv_delcc(1) - delcc0*inv_delcc(2))
1226        dtweightde_tmp(ind_c(2),ieps2,ieps1) = dtweightde_tmp(ind_c(2),ieps2,ieps1) + &
1227 &         ii3*0.5d0*delcc0*inv_delcc(1)*deleps1*inv_epsilon1(ind_c(2),4)
1228        dtweightde_tmp(ind_c(3),ieps2,ieps1) = dtweightde_tmp(ind_c(3),ieps2,ieps1) + &
1229 &         ii3*0.5d0*delcc0*inv_delcc(2)*deleps1*inv_epsilon1(ind_c(3),4)
1230        deleps2 = deleps2 + deltaene2
1231      end do
1232 
1233      deleps1 = deleps1 + deltaene1
1234    end do
1235 
1236    eps1 = eps1 + (nn1_4-nn1_3)*deltaene1
1237    !
1238    !
1239    !  interval e4 < eps < enemax
1240    !
1241    do ieps1=nn1_4+1,nene1
1242      ! dtweightde unchanged by this tetrahedron
1243    end do
1244 
1245    ! if we have a fully degenerate tetrahedron,
1246    ! 1) the tweight is a Heaviside (step) function, which is correct above, but
1247    ! 2) the dtweightde should contain a Dirac function: add a Gaussian here
1248 
1249    ! TODO: add treatment in double tetra case
1250    !  end degenerate tetrahedron if
1251 
1252    ! the following blas calls are not working systematically, or do not give speed ups, strange...
1253    !call daxpy (nene, 1.d0, dtweightde_tmp(:,1), 1, dtweightde_t(:,ind_ibz(1)), 1)
1254    !call daxpy (nene, 1.d0, dtweightde_tmp(:,2), 1, dtweightde_t(:,ind_ibz(2)), 1)
1255    !call daxpy (nene, 1.d0, dtweightde_tmp(:,3), 1, dtweightde_t(:,ind_ibz(3)), 1)
1256    !call daxpy (nene, 1.d0, dtweightde_tmp(:,4), 1, dtweightde_t(:,ind_ibz(4)), 1)
1257 
1258    do ieps2 = 1, nene2
1259      dtweightde(ind_k(1),:,ieps2) = dtweightde(ind_k(1),:,ieps2) + dtweightde_tmp(1,ieps2,:)
1260      dtweightde(ind_k(2),:,ieps2) = dtweightde(ind_k(2),:,ieps2) + dtweightde_tmp(2,ieps2,:)
1261      dtweightde(ind_k(3),:,ieps2) = dtweightde(ind_k(3),:,ieps2) + dtweightde_tmp(3,ieps2,:)
1262      dtweightde(ind_k(4),:,ieps2) = dtweightde(ind_k(4),:,ieps2) + dtweightde_tmp(4,ieps2,:)
1263      !tweight(nkpt,nene1,nene2)
1264    end do
1265 
1266  end do ! itetra
1267 
1268  ! transpose: otherwise the data access is crap and the code slows by an order of magnitude
1269  TETRA_DEALLOCATE(tweight_tmp)
1270  TETRA_DEALLOCATE(dtweightde_tmp)
1271 
1272 end subroutine get_dbl_tetra_weight

m_tetrahedron/get_onetetra_ [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

 get_onetetra_

FUNCTION

 Private function to calculate the contributions to the weights due to a single tetrahedron.
 Extracted from get_tetra_weight

SOURCE

1472 pure subroutine get_onetetra_(tetra,itetra,eigen_1tetra,enemin,enemax,max_occ,nene,bcorr, &
1473 &  tweight_tmp,dtweightde_tmp)
1474 
1475 !Arguments ------------------------------------
1476 !scalars
1477  integer,intent(in) :: nene,bcorr,itetra
1478  type(t_tetrahedron), intent(in) :: tetra
1479  real(dp) ,intent(in) :: enemax,enemin,max_occ
1480 !arrays
1481  ! MGTODO: This layout is not optimal (lots of cache thrashing, I will optimize it later on)
1482  real(dp), intent(out) ::  tweight_tmp(nene, 4)
1483  real(dp), intent(out) :: dtweightde_tmp(nene, 4)
1484  real(dp),intent(in)  :: eigen_1tetra(4)
1485 
1486 !Local variables-------------------------------
1487 !  needed for gaussian replacement of Dirac functions
1488 !  the three coefficients of the DOS as quadratic form,
1489 !    in the interval [eig(ikpt-1), eig(ikpt)]
1490 !    for ikpt = 1 we add a point below eigen(1) which doesnt
1491 !    contribute to the DOS in any tetrahedron
1492 !scalars
1493  integer :: ieps,nn1,nn2,nn3,nn4
1494  real(dp)  :: cc,cc1,cc2,cc3,dcc1de,dcc2de,dcc3de,dccde,deltaene,eps
1495  real(dp)  :: epsilon21,epsilon31,epsilon32,epsilon41,epsilon42,epsilon43
1496  real(dp)  :: gau_prefactor,gau_width,gau_width2,inv_epsilon21,inv_epsilon31,gval
1497  real(dp)  :: inv_epsilon32,inv_epsilon41,inv_epsilon42,inv_epsilon43
1498  real(dp)  :: deleps1, deleps2, deleps3, deleps4
1499  real(dp)  :: invepsum, cc_pre, dccde_pre
1500  real(dp)  :: cc1_pre, cc2_pre, cc3_pre
1501  real(dp)  :: cc_tmp, dccde_tmp
1502  real(dp)  :: dcc1de_pre, dcc2de_pre, dcc3de_pre
1503  real(dp)  :: tmp,volconst,volconst_mult
1504 
1505 ! *********************************************************************
1506 
1507  volconst = tetra%vv/4.d0
1508 
1509  deltaene = (enemax-enemin) / (nene-1)
1510 
1511  ! This is output
1512  tweight_tmp = zero; dtweightde_tmp = zero
1513 
1514  volconst_mult = max_occ*volconst*dble(tetra%tetra_mult(itetra))
1515 
1516  ! all notations are from Blochl PRB 49 16223 [[cite:Bloechl1994a]] Appendix B
1517  epsilon21 = eigen_1tetra(2)-eigen_1tetra(1)
1518  epsilon31 = eigen_1tetra(3)-eigen_1tetra(1)
1519  epsilon41 = eigen_1tetra(4)-eigen_1tetra(1)
1520  epsilon32 = eigen_1tetra(3)-eigen_1tetra(2)
1521  epsilon42 = eigen_1tetra(4)-eigen_1tetra(2)
1522  epsilon43 = eigen_1tetra(4)-eigen_1tetra(3)
1523  inv_epsilon21 = zero; if (epsilon21 > tol6) inv_epsilon21 = 1.d0 / epsilon21
1524  inv_epsilon31 = zero; if (epsilon31 > tol6) inv_epsilon31 = 1.d0 / epsilon31
1525  inv_epsilon41 = zero; if (epsilon41 > tol6) inv_epsilon41 = 1.d0 / epsilon41
1526  inv_epsilon32 = zero; if (epsilon32 > tol6) inv_epsilon32 = 1.d0 / epsilon32
1527  inv_epsilon42 = zero; if (epsilon42 > tol6) inv_epsilon42 = 1.d0 / epsilon42
1528  inv_epsilon43 = zero; if (epsilon43 > tol6) inv_epsilon43 = 1.d0 / epsilon43
1529 
1530  nn1 = int((eigen_1tetra(1)-enemin)/deltaene)+1
1531  nn2 = int((eigen_1tetra(2)-enemin)/deltaene)+1
1532  nn3 = int((eigen_1tetra(3)-enemin)/deltaene)+1
1533  nn4 = int((eigen_1tetra(4)-enemin)/deltaene)+1
1534 
1535  nn1 = max(1,nn1)
1536  nn1 = min(nn1,nene)
1537  nn2 = max(1,nn2)
1538  nn2 = min(nn2,nene)
1539  nn3 = max(1,nn3)
1540  nn3 = min(nn3,nene)
1541  nn4 = max(1,nn4)
1542  nn4 = min(nn4,nene)
1543 
1544  eps = enemin+nn1*deltaene
1545  !
1546  !interval enemin < eps < e1 nothing to do
1547  !
1548  !
1549  !interval e1 < eps < e2
1550  !
1551  deleps1 = eps-eigen_1tetra(1)
1552  cc_pre = volconst_mult*inv_epsilon21*inv_epsilon31*inv_epsilon41
1553  invepsum = inv_epsilon21+inv_epsilon31+inv_epsilon41
1554  dccde_pre = 3.d0*volconst_mult*inv_epsilon21*inv_epsilon31*inv_epsilon41
1555  do ieps=nn1+1,nn2
1556    cc = cc_pre * deleps1*deleps1*deleps1
1557    tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + cc*(4.d0-deleps1*invepsum)
1558    tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + cc*deleps1*inv_epsilon21
1559    tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + cc*deleps1*inv_epsilon31
1560    tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + cc*deleps1*inv_epsilon41
1561 
1562    dccde = dccde_pre * deleps1*deleps1
1563    dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + dccde*(4.d0 - deleps1*invepsum) -cc*invepsum
1564    dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + (dccde*deleps1 + cc) * inv_epsilon21
1565    dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + (dccde*deleps1 + cc) * inv_epsilon31
1566    dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + (dccde*deleps1 + cc) * inv_epsilon41
1567 
1568    if (bcorr == 1) then
1569      ! bxu, correction terms based on Bloechl's paper
1570      tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
1571 &     4.d0*dccde_pre*deleps1*deleps1*(epsilon21+epsilon31+epsilon41)/40.d0
1572      tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
1573 &     4.d0*dccde_pre*deleps1*deleps1*(-epsilon21+epsilon32+epsilon42)/40.d0
1574      tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
1575 &     4.d0*dccde_pre*deleps1*deleps1*(-epsilon31-epsilon32+epsilon43)/40.d0
1576      tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
1577 &     4.d0*dccde_pre*deleps1*deleps1*(-epsilon41-epsilon42-epsilon43)/40.d0
1578 
1579      dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + &
1580 &     8.d0*dccde_pre*deleps1*(epsilon21+epsilon31+epsilon41)/40.d0
1581      dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + &
1582 &     8.d0*dccde_pre*deleps1*(-epsilon21+epsilon32+epsilon42)/40.d0
1583      dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + &
1584 &     8.d0*dccde_pre*deleps1*(-epsilon31-epsilon32+epsilon43)/40.d0
1585      dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + &
1586 &     8.d0*dccde_pre*deleps1*(-epsilon41-epsilon42-epsilon43)/40.d0
1587    end if
1588 
1589    deleps1 = deleps1 + deltaene
1590  end do
1591 
1592  eps = eps + (nn2-nn1)*deltaene
1593  !
1594  !  interval e2 < eps < e3
1595  !
1596  deleps1 = eps-eigen_1tetra(1)
1597  deleps2 = eps-eigen_1tetra(2)
1598  deleps3 = eigen_1tetra(3)-eps
1599  deleps4 = eigen_1tetra(4)-eps
1600 
1601  cc1_pre = volconst_mult*inv_epsilon31*inv_epsilon41
1602  cc2_pre = volconst_mult*inv_epsilon41*inv_epsilon32*inv_epsilon31
1603  cc3_pre = volconst_mult*inv_epsilon42*inv_epsilon32*inv_epsilon41
1604 
1605  dcc1de_pre = 2.d0*cc1_pre
1606  dcc2de_pre = cc2_pre
1607  dcc3de_pre = cc3_pre
1608  do ieps=nn2+1,nn3
1609    cc1 = cc1_pre * deleps1*deleps1
1610    cc2 = cc2_pre * deleps1*deleps2*deleps3
1611    cc3 = cc3_pre * deleps2*deleps2*deleps4
1612 
1613    tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
1614 &   cc1 + (cc1+cc2)*deleps3*inv_epsilon31 + (cc1+cc2+cc3)*deleps4*inv_epsilon41
1615    tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
1616 &   cc1+cc2+cc3+(cc2+cc3)*deleps3*inv_epsilon32 + cc3*deleps4*inv_epsilon42
1617    tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
1618 &   (cc1+cc2)*deleps1*inv_epsilon31 + (cc2+cc3)*deleps2*inv_epsilon32
1619    tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
1620 &   (cc1+cc2+cc3)*deleps1*inv_epsilon41 + cc3*deleps2*inv_epsilon42
1621 
1622 
1623    dcc1de = dcc1de_pre * deleps1
1624    dcc2de = dcc2de_pre * (-deleps1*deleps2  +deleps1*deleps3  +deleps2*deleps3)
1625    dcc3de = dcc3de_pre * (2.d0*deleps2*deleps4  -deleps2*deleps2)
1626 
1627    dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) &
1628 &   + dcc1de &
1629 &   + ((dcc1de+dcc2de)*deleps3 -(cc1+cc2)) * inv_epsilon31 &
1630 &   + ((dcc1de+dcc2de+dcc3de)*deleps4 -(cc1+cc2+cc3)) * inv_epsilon41
1631    dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) &
1632 &   + dcc1de+dcc2de+dcc3de &
1633 &   + ((dcc2de+dcc3de)*deleps3 -(cc2+cc3) ) * inv_epsilon32 &
1634 &   + (dcc3de*deleps4  -cc3 ) * inv_epsilon42
1635    dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) &
1636 &   + ((dcc1de+dcc2de)*deleps1 + (cc1+cc2) ) * inv_epsilon31 &
1637 &   + ((dcc2de+dcc3de)*deleps2 + (cc2+cc3) ) * inv_epsilon32
1638    dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) &
1639 &   + ((dcc1de+dcc2de+dcc3de)*deleps1 + (cc1+cc2+cc3) ) * inv_epsilon41 &
1640 &   + (dcc3de*deleps2 + cc3) * inv_epsilon42
1641 
1642  if (bcorr == 1) then
1643    ! bxu, correction terms based on Bloechl's paper
1644    ! The correction terms may cause the dtweightde become negative
1645    tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
1646 &   4.d0*cc1_pre* &
1647 &   (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
1648 &   (epsilon21+epsilon31+epsilon41)/40.d0
1649    tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
1650 &   4.d0*cc1_pre* &
1651 &   (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
1652 &   (-epsilon21+epsilon32+epsilon42)/40.d0
1653    tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
1654 &   4.d0*cc1_pre* &
1655 &   (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
1656 &   (-epsilon31-epsilon32+epsilon43)/40.d0
1657    tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
1658 &   4.d0*cc1_pre* &
1659 &   (3.d0*epsilon21+6.d0*deleps2-3.d0*(epsilon31+epsilon42)*deleps2**2.d0*inv_epsilon32*inv_epsilon42)* &
1660 &   (-epsilon41-epsilon42-epsilon43)/40.d0
1661 
1662    dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + &
1663 &   4.d0*cc1_pre* &
1664 &   (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
1665 &   (epsilon21+epsilon31+epsilon41)/40.d0
1666    dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + &
1667 &   4.d0*cc1_pre* &
1668 &   (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
1669 &   (-epsilon21+epsilon32+epsilon42)/40.d0
1670    dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + &
1671 &   4.d0*cc1_pre* &
1672 &   (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
1673 &   (-epsilon31-epsilon32+epsilon43)/40.d0
1674    dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + &
1675 &   4.d0*cc1_pre* &
1676 &   (6.d0-6.d0*(epsilon31+epsilon42)*deleps2*inv_epsilon32*inv_epsilon42)* &
1677 &   (-epsilon41-epsilon42-epsilon43)/40.d0
1678   end if
1679 
1680   deleps1 = deleps1 + deltaene
1681   deleps2 = deleps2 + deltaene
1682   deleps3 = deleps3 - deltaene
1683   deleps4 = deleps4 - deltaene
1684  end do
1685 
1686  eps = eps + (nn3-nn2)*deltaene
1687  !
1688  !  interval e3 < eps < e4
1689  !
1690  deleps4 = eigen_1tetra(4)-eps
1691  cc_pre = volconst_mult*inv_epsilon41*inv_epsilon42*inv_epsilon43
1692  invepsum = inv_epsilon41+inv_epsilon42+inv_epsilon43
1693  dccde_pre = -3.d0*cc_pre
1694  do ieps=nn3+1,nn4
1695    cc = cc_pre * deleps4*deleps4*deleps4
1696    cc_tmp = cc * deleps4
1697    tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + volconst_mult - cc_tmp*inv_epsilon41
1698    tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + volconst_mult - cc_tmp*inv_epsilon42
1699    tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + volconst_mult - cc_tmp*inv_epsilon43
1700    tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + volconst_mult - cc*4.d0 + cc_tmp*invepsum
1701 
1702    dccde = dccde_pre * deleps4*deleps4
1703    dccde_tmp = -dccde*deleps4 + cc
1704    dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + dccde_tmp * inv_epsilon41
1705    dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + dccde_tmp * inv_epsilon42
1706    dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + dccde_tmp * inv_epsilon43
1707    dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) - dccde*4.d0 - dccde_tmp*invepsum
1708 
1709    if (bcorr == 1) then
1710      ! bxu, correction terms based on Bloechl's paper
1711      ! The correction terms may cause the dtweightde become negative
1712      tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + &
1713 &     12.d0*cc_pre*deleps4*deleps4*(epsilon21+epsilon31+epsilon41)/40.d0
1714      tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + &
1715 &     12.d0*cc_pre*deleps4*deleps4*(-epsilon21+epsilon32+epsilon42)/40.d0
1716      tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + &
1717 &     12.d0*cc_pre*deleps4*deleps4*(-epsilon31-epsilon32+epsilon43)/40.d0
1718      tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + &
1719 &     12.d0*cc_pre*deleps4*deleps4*(-epsilon41-epsilon42-epsilon43)/40.d0
1720 
1721      dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) - &
1722 &     24.d0*cc_pre*deleps4*(epsilon21+epsilon31+epsilon41)/40.d0
1723      dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) - &
1724 &     24.d0*cc_pre*deleps4*(-epsilon21+epsilon32+epsilon42)/40.d0
1725      dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) - &
1726 &     24.d0*cc_pre*deleps4*(-epsilon31-epsilon32+epsilon43)/40.d0
1727      dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) - &
1728 &     24.d0*cc_pre*deleps4*(-epsilon41-epsilon42-epsilon43)/40.d0
1729    end if
1730 
1731    deleps4 = deleps4 - deltaene
1732  end do
1733  eps = eps + (nn4-nn3)*deltaene
1734  !
1735  !
1736  !  interval e4 < eps < enemax
1737  !
1738  do ieps=nn4+1,nene
1739    tweight_tmp(ieps,1) = tweight_tmp(ieps,1) + volconst_mult
1740    tweight_tmp(ieps,2) = tweight_tmp(ieps,2) + volconst_mult
1741    tweight_tmp(ieps,3) = tweight_tmp(ieps,3) + volconst_mult
1742    tweight_tmp(ieps,4) = tweight_tmp(ieps,4) + volconst_mult
1743    ! dtweightde unchanged by this tetrahedron
1744  end do
1745 
1746  !
1747  !  if we have a fully degenerate tetrahedron,
1748  !  1) the tweight is a Heaviside (step) function, which is correct above, but
1749  !  2) the dtweightde should contain a Dirac function: add a Gaussian here
1750  !
1751  if (epsilon41 < tol6) then
1752 
1753    !  to ensure the gaussian will integrate properly:
1754    !  WARNING: this smearing could be problematic if too large
1755    !  and doesnt integrate well if its too small
1756    gau_width = 10.0d0*deltaene
1757    gau_width2 = 1.0 / gau_width / gau_width
1758    gau_prefactor = volconst_mult / gau_width / sqrtpi
1759    !
1760    ! average position since bracket for epsilon41 is relatively large
1761    cc = (eigen_1tetra(1)+eigen_1tetra(2)+eigen_1tetra(3)+eigen_1tetra(4))/4.d0
1762    eps = enemin
1763    do ieps=1,nene
1764      tmp = eps - cc
1765      gval = gau_prefactor*exp(-tmp*tmp*gau_width2)
1766      ! MG TODO: I think this is not correct, because we have divided by 4 so
1767      ! the other points should be accumulated as well.
1768      ! There are however changes in the unit tests if I activate these lines...
1769      !dtweightde_tmp(ieps,1) = dtweightde_tmp(ieps,1) + gval
1770      !dtweightde_tmp(ieps,2) = dtweightde_tmp(ieps,2) + gval
1771      !dtweightde_tmp(ieps,3) = dtweightde_tmp(ieps,3) + gval
1772      dtweightde_tmp(ieps,4) = dtweightde_tmp(ieps,4) + gval
1773      eps = eps + deltaene
1774    end do
1775  end if ! end degenerate tetrahedron if
1776 
1777 end subroutine get_onetetra_

m_tetrahedron/get_tetra_weight [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

 get_tetra_weight

FUNCTION

 calculate integration weights and their derivatives from Blochl et al PRB 49 16223 [[cite:Bloechl1994a]]

INPUTS

 eigen_in(nkpt)=eigenenergies for each k point
 enemin=minimal energy for DOS
 enemax=maximal energy for DOS
 max_occ=maximal occupation number (2 for nsppol=1, 1 for nsppol=2)
 nene=number of energies for DOS
 nkpt=number of irreducible kpoints
 tetra<t_tetrahedron>
   %ntetra=number of tetrahedra
   %tetra_full(4,2,ntetra)=for each irred tetrahedron, the list of k point vertices
     1 -> irred kpoint   2 -> fullkpt
   %tetra_mult(ntetra)=for each irred tetrahedron, its multiplicity
   %vv = ratio of volume of one tetrahedron in reciprocal space to full BZ volume
 bcorr=1 to include Blochl correction else 0.
 comm=MPI communicator

OUTPUT

  tweight(nkpt,nene) = integration weights for each irred kpoint from all adjacent tetrahedra
  dtweightde(nkpt,nene) = derivative of tweight wrt energy

SOURCE

642 ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643 ! THIS FUNCTION IS DEPRECATED, USE tetra_blochl_weights
644 ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
645 subroutine get_tetra_weight(eigen_in,enemin,enemax,max_occ,nene,nkpt,tetra,&
646   bcorr,tweight,dtweightde,comm)
647 
648 !Arguments ------------------------------------
649 !scalars
650  integer,intent(in) :: nene,nkpt,bcorr,comm
651  type(t_tetrahedron), intent(in) :: tetra
652  real(dp) ,intent(in) :: enemax,enemin,max_occ
653 !arrays
654  real(dp) ,intent(in) :: eigen_in(nkpt)
655  real(dp) ,intent(out) :: dtweightde(nkpt,nene),tweight(nkpt,nene)
656 
657 !Local variables-------------------------------
658  real(dp), allocatable :: dtweightde_ek(:, :), tweight_ek(:, :)
659 
660 ! *********************************************************************
661 
662  TETRA_ALLOCATE(dtweightde_ek, (nene, nkpt))
663  TETRA_ALLOCATE(tweight_ek, (nene, nkpt))
664 
665  call tetra_blochl_weights(tetra,eigen_in,enemin,enemax,max_occ,nene,nkpt,bcorr,tweight_ek,dtweightde_ek,comm)
666 
667  ! transpose: otherwise the data access is crap and the code slows by an order of magnitude
668  tweight    = transpose(tweight_ek)
669  dtweightde = transpose(dtweightde_ek)
670 
671  TETRA_DEALLOCATE(dtweightde_ek)
672  TETRA_DEALLOCATE(tweight_ek)
673 
674 end subroutine get_tetra_weight

m_tetrahedron/init_tetra [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

 init_tetra

FUNCTION

 get tetrahedra characterized by apexes

INPUTS

  indkpt(nkpt_fullbz)=indexes of irred kpoints equivalent to kpt_fullbz
  gprimd(3,3) = reciprocal space vectors
  klatt(3,3)=reciprocal of lattice vectors for full kpoint grid
  kpt_fullbz(3,nkpt_fullbz)=kpoints in full brillouin zone
  nkpt_fullbz=number of kpoints in full brillouin zone
  comm= MPI communicator

OUTPUT

  tetra%tetra_full(4,2,ntetra)=for each tetrahedron,
     the different instances of the tetrahedron (fullbz kpoints)
  tetra%tetra_mult(ntetra) = store multiplicity of each irred tetrahedron
  tetra%tetra_wrap(3,4,ntetra) = store flag to wrap tetrahedron summit into IBZ
  tetra%ntetra = final number of irred tetra (dimensions of tetra_* remain larger)
  tetra%vv = tetrahedron volume divided by full BZ volume

SOURCE

184 subroutine init_tetra(indkpt, gprimd, klatt, kpt_fullbz, nkpt_fullbz, tetra, ierr, errorstring, comm)
185 
186 !Arguments ------------------------------------
187 !scalars
188  integer,intent(in) :: nkpt_fullbz, comm
189  integer, intent(out) :: ierr
190  character(len=80), intent(out) :: errorstring
191  type(t_tetrahedron),intent(out) :: tetra
192 !arrays
193  integer,intent(in) :: indkpt(nkpt_fullbz)
194  real(dp) ,intent(in) :: gprimd(3,3),klatt(3,3),kpt_fullbz(3,nkpt_fullbz)
195 
196 !Local variables-------------------------------
197 !scalars
198  integer :: ialltetra,ikpt2,ikpt_full,isummit,itetra,jalltetra,jsummit
199  integer :: ii,jj,ikibz,nkpt_ibz, my_rank, nprocs
200  integer :: symrankkpt,mtetra,itmp,ntetra_irred
201  real(dp) :: shift1,shift2,shift3, rcvol,hashfactor
202  !real :: cpu_start, cpu_stop
203  type(krank_t) :: krank
204 !arrays
205  integer :: ind_ibz(4), tetra_shifts(3,4,6)  ! 3 dimensions, 4 summits, and 6 tetrahedra / kpoint box
206  real(dp)  :: k1(3),k2(3),k3(3)
207  integer,allocatable :: tetra_full_(:,:,:)
208  integer,allocatable :: tetra_mult_(:)
209  integer,allocatable :: tetra_wrap_(:,:,:)
210  integer, allocatable :: reforder(:)
211  integer, allocatable :: irred_itetra(:)
212  real(dp), allocatable :: tetra_hash(:)
213 
214 ! *********************************************************************
215 
216  !call cpu_time(cpu_start)
217 
218  my_rank = 0; nprocs = 1
219 #ifdef HAVE_LIBTETRA_ABINIT
220  my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm)
221 #endif
222 
223  ierr = 0
224  errorstring = ""
225 !jmb
226  shift1 = zero
227  shift2 = zero
228  shift3 = zero
229 
230  tetra%klatt = klatt
231 
232  mtetra = 6 * nkpt_fullbz
233  TETRA_ALLOCATE(tetra_full_, (4,2,mtetra))
234  TETRA_ALLOCATE(tetra_mult_, (mtetra))
235  TETRA_ALLOCATE(tetra_wrap_, (3,4,mtetra))
236 
237  tetra_mult_ = 1
238  tetra_full_ = 0
239  tetra_wrap_ = 0
240 
241 ! tetra_shifts(:,1,1) = (/0,0,0/)
242 ! tetra_shifts(:,2,1) = (/0,1,0/)
243 ! tetra_shifts(:,3,1) = (/0,1,1/)
244 ! tetra_shifts(:,4,1) = (/1,1,0/)
245 ! tetra_shifts(:,1,2) = (/0,0,0/)
246 ! tetra_shifts(:,2,2) = (/0,1,1/)
247 ! tetra_shifts(:,3,2) = (/1,1,0/)
248 ! tetra_shifts(:,4,2) = (/1,1,1/)
249 ! tetra_shifts(:,1,3) = (/0,0,0/)
250 ! tetra_shifts(:,2,3) = (/1,0,0/)
251 ! tetra_shifts(:,3,3) = (/1,1,0/)
252 ! tetra_shifts(:,4,3) = (/1,1,1/)
253 ! tetra_shifts(:,1,4) = (/0,0,0/)
254 ! tetra_shifts(:,2,4) = (/0,0,1/)
255 ! tetra_shifts(:,3,4) = (/1,0,0/)
256 ! tetra_shifts(:,4,4) = (/1,1,1/)
257 ! tetra_shifts(:,1,5) = (/0,0,1/)
258 ! tetra_shifts(:,2,5) = (/1,0,0/)
259 ! tetra_shifts(:,3,5) = (/1,0,1/)
260 ! tetra_shifts(:,4,5) = (/1,1,1/)
261 ! tetra_shifts(:,1,6) = (/0,0,0/)
262 ! tetra_shifts(:,2,6) = (/0,0,1/)
263 ! tetra_shifts(:,3,6) = (/0,1,1/)
264 ! tetra_shifts(:,4,6) = (/1,1,1/)
265 
266  ! bxu, the following division scheme is according to Bloechl's paper
267  tetra_shifts(:,1,1) = (/0,0,0/)
268  tetra_shifts(:,2,1) = (/1,0,0/)
269  tetra_shifts(:,3,1) = (/0,1,0/)
270  tetra_shifts(:,4,1) = (/1,0,1/)
271  tetra_shifts(:,1,2) = (/1,0,0/)
272  tetra_shifts(:,2,2) = (/1,1,0/)
273  tetra_shifts(:,3,2) = (/0,1,0/)
274  tetra_shifts(:,4,2) = (/1,0,1/)
275  tetra_shifts(:,1,3) = (/0,1,0/)
276  tetra_shifts(:,2,3) = (/1,1,0/)
277  tetra_shifts(:,3,3) = (/1,0,1/)
278  tetra_shifts(:,4,3) = (/1,1,1/)
279  tetra_shifts(:,1,4) = (/0,0,0/)
280  tetra_shifts(:,2,4) = (/0,1,0/)
281  tetra_shifts(:,3,4) = (/0,0,1/)
282  tetra_shifts(:,4,4) = (/1,0,1/)
283  tetra_shifts(:,1,5) = (/0,0,1/)
284  tetra_shifts(:,2,5) = (/1,0,1/)
285  tetra_shifts(:,3,5) = (/0,1,0/)
286  tetra_shifts(:,4,5) = (/0,1,1/)
287  tetra_shifts(:,1,6) = (/0,1,0/)
288  tetra_shifts(:,2,6) = (/1,0,1/)
289  tetra_shifts(:,3,6) = (/0,1,1/)
290  tetra_shifts(:,4,6) = (/1,1,1/)
291 
292  ! Make full k-point rank arrays
293  ! TODO: Lot of memory allocated here if dense mesh e.g ~ 300 ** 3
294  krank = krank_new(nkpt_fullbz, kpt_fullbz)
295 
296  ialltetra = 1
297  do ikpt_full=1,nkpt_fullbz
298    do itetra=1,6
299      !ialltetra = itetra + (ikpt_full -1) * 6
300      !if (mod(ialltetra, nprocs) /= my_rank) cycle ! MPI parallelism.
301      do isummit=1,4
302        k1(:) = kpt_fullbz(:,ikpt_full) &
303         + tetra_shifts(1,isummit,itetra)*klatt(:,1) &
304         + tetra_shifts(2,isummit,itetra)*klatt(:,2) &
305         + tetra_shifts(3,isummit,itetra)*klatt(:,3)
306 
307        ! Find full kpoint which is summit isummit of tetrahedron itetra around full kpt ikpt_full !
308        symrankkpt =  krank%get_rank(k1)
309        ikpt2 = krank%invrank(symrankkpt)
310        if (ikpt2 < 1) then
311          errorstring='Error in ranking k-points - exiting with un-initialized tetrahedra.'
312          ierr = 2
313          call krank%free()
314          TETRA_ALLOCATE(tetra%tetra_full, (4,2,1))
315          TETRA_ALLOCATE(tetra%tetra_mult, (1))
316          TETRA_ALLOCATE(tetra%tetra_wrap, (3,4,1))
317          TETRA_DEALLOCATE(tetra_full_)
318          TETRA_DEALLOCATE(tetra_mult_)
319          TETRA_DEALLOCATE(tetra_wrap_)
320          return
321        end if
322 
323        ! Store irreducible kpoint equivalent to kpt_fullbz(:,ikpt2)
324        tetra_full_(isummit,1,ialltetra) = indkpt(ikpt2)
325        tetra_full_(isummit,2,ialltetra) = ikpt2
326        shift1 = k1(1)-kpt_fullbz(1,ikpt2)
327        shift2 = k1(2)-kpt_fullbz(2,ikpt2)
328        shift3 = k1(3)-kpt_fullbz(3,ikpt2)
329        if (shift1>0.5d0) then
330          tetra_wrap_(1,isummit,ialltetra) = 1
331        else if (shift1<-0.5d0) then
332          tetra_wrap_(1,isummit,ialltetra) = -1
333        end if
334        if (shift2>0.5d0) then
335          tetra_wrap_(2,isummit,ialltetra) = 1
336        else if (shift2<-0.5d0) then
337          tetra_wrap_(2,isummit,ialltetra) = -1
338        end if
339        if (shift3>0.5d0) then
340          tetra_wrap_(3,isummit,ialltetra) = 1
341        else if (shift3<-0.5d0) then
342          tetra_wrap_(3,isummit,ialltetra) = -1
343        end if
344 
345        ! sort itetra summits
346        ! TODO: replace with sort_int
347        do jsummit=isummit,2,-1
348          if ( tetra_full_(jsummit,1,ialltetra)  <  tetra_full_(jsummit-1,1,ialltetra) ) then
349            itmp = tetra_full_(jsummit,1,ialltetra)
350            tetra_full_(jsummit,1,ialltetra) = tetra_full_(jsummit-1,1,ialltetra)
351            tetra_full_(jsummit-1,1,ialltetra) = itmp
352            itmp = tetra_full_(jsummit,2,ialltetra)
353            tetra_full_(jsummit,2,ialltetra) = tetra_full_(jsummit-1,2,ialltetra)
354            tetra_full_(jsummit-1,2,ialltetra) = itmp
355            ! keep fullbz_kpt tetrahedra points in same order
356            itmp = tetra_wrap_(1,jsummit,ialltetra)
357            tetra_wrap_(1,jsummit,ialltetra) = tetra_wrap_(1,jsummit-1,ialltetra)
358            tetra_wrap_(1,jsummit-1,ialltetra) = itmp
359            itmp = tetra_wrap_(2,jsummit,ialltetra)
360            tetra_wrap_(2,jsummit,ialltetra) = tetra_wrap_(2,jsummit-1,ialltetra)
361            tetra_wrap_(2,jsummit-1,ialltetra) = itmp
362            itmp = tetra_wrap_(1,jsummit,ialltetra)
363            tetra_wrap_(3,jsummit,ialltetra) = tetra_wrap_(3,jsummit-1,ialltetra)
364            tetra_wrap_(3,jsummit-1,ialltetra) = itmp
365          end if
366        end do ! jsummit
367 
368      end do ! isummit
369 
370      if (ialltetra > mtetra) then
371        write (errorstring, '(3a,i0,a,i0)' ) &
372         'init_tetra: BUG - ',&
373         ' ialltetra > mtetra ',&
374         ' ialltetra=  ',ialltetra,', mtetra= ',mtetra
375        ierr = 1
376        return
377      end if
378      ialltetra = ialltetra+1
379    end do ! itetra
380  end do ! ikpt_full
381 
382  !call cpu_time(cpu_stop)
383  !write(*,*)"tetra_init ikpt_loop:", cpu_stop - cpu_start
384  !cpu_start = cpu_stop
385 
386  call krank%free()
387 
388  rcvol = abs (gprimd(1,1)*(gprimd(2,2)*gprimd(3,3)-gprimd(3,2)*gprimd(2,3)) &
389 & -gprimd(2,1)*(gprimd(1,2)*gprimd(3,3)-gprimd(3,2)*gprimd(1,3)) &
390 & +gprimd(3,1)*(gprimd(1,2)*gprimd(2,3)-gprimd(2,2)*gprimd(1,3)))
391 
392  ! Volume of all tetrahedra should be the same as that of tetra 1
393  ! this is the volume of 1 tetrahedron, should be coherent with notation in Lehmann & Taut
394  k1(:) = gprimd(:,1)*klatt(1,1) +  gprimd(:,2)*klatt(2,1) +  gprimd(:,3)*klatt(3,1)
395  k2(:) = gprimd(:,1)*klatt(1,2) +  gprimd(:,2)*klatt(2,2) +  gprimd(:,3)*klatt(3,2)
396  k3(:) = gprimd(:,1)*klatt(1,3) +  gprimd(:,2)*klatt(2,3) +  gprimd(:,3)*klatt(3,3)
397  tetra%vv  = abs (k1(1)*(k2(2)*k3(3)-k2(3)*k3(2)) &
398 & -k1(2)*(k2(1)*k3(3)-k2(3)*k3(1)) &
399 & +k1(3)*(k2(1)*k3(2)-k2(2)*k3(1))) / 6.d0 / rcvol
400 
401  ! eliminate equivalent tetrahedra by symmetry and account for them in multiplicity tetra_mult
402  tetra%ntetra = mtetra
403 
404  ! FIXME: could we replace this with a ranking algorithm to avoid the O(tetra%ntetra^2) step? For example:
405  ! get tetrahedron rank - problem too many combinations in principle = nkpt_irred^4 - only a few used in practice
406  ! sort ranks and keep indices
407 
408  ! make hash table = tetra_full_(1)*nkptirred**3+tetra_full_(2)*nkptirred**2+tetra_full_(3)*nkptirred**1+tetra_full_(4)
409 
410  hashfactor = 100.d0 ! *acos(-1.d0) ! 100 pi should be far from an integer...
411  TETRA_ALLOCATE(tetra_hash, (tetra%ntetra))
412  TETRA_ALLOCATE(reforder, (tetra%ntetra))
413 
414  !MG: In principle the order of the indices should not matter.
415  do ialltetra=1, tetra%ntetra
416    tetra_hash(ialltetra) = tetra_full_(1,1,ialltetra)*hashfactor**3+&
417 &      tetra_full_(2,1,ialltetra)*hashfactor**2+&
418 &      tetra_full_(3,1,ialltetra)*hashfactor**1+&
419 &      tetra_full_(4,1,ialltetra)
420    reforder(ialltetra) = ialltetra
421  end do
422 
423  call sort_tetra(tetra%ntetra, tetra_hash, reforder, tol6)
424  ! Most of the wall-time is spent in the  preamble of this routine (up to this point).
425  ! sort_tetra is not easy to parallelize...
426 
427  ! determine number of tetra after reduction
428  TETRA_ALLOCATE(irred_itetra, (tetra%ntetra))
429  jalltetra = 1
430  irred_itetra(1) = 1
431  do ialltetra=2, tetra%ntetra
432    if (abs(tetra_hash(ialltetra)-tetra_hash(ialltetra-1)) > tol6) then
433      ! found a new series
434      jalltetra = jalltetra + 1
435    end if
436    irred_itetra(ialltetra) = jalltetra
437  end do
438 
439  ! reset number of tetra
440  ntetra_irred = jalltetra
441 
442  ! allocate definitive tetra arrays and transfer to new arrays
443  TETRA_ALLOCATE(tetra%tetra_full, (4,2,ntetra_irred))
444  TETRA_ALLOCATE(tetra%tetra_mult, (ntetra_irred))
445  TETRA_ALLOCATE(tetra%tetra_wrap, (3,4,ntetra_irred))
446 
447  ! eliminate equal rank tetrahedra and accumulate multiplicity into first one
448  tetra%tetra_full = 0
449  tetra%tetra_mult = 0
450  tetra%tetra_wrap = 0
451  jalltetra = 1
452  tetra%tetra_full(:,:,1) = tetra_full_(:,:,reforder(1))
453  tetra%tetra_mult(1) = 1
454  tetra%tetra_wrap(:,:,1) = tetra_wrap_(:,:,reforder(1))
455  do ialltetra=2, tetra%ntetra
456    ! TODO: check if tolerance is adapted
457    if (abs(tetra_hash(ialltetra)-tetra_hash(ialltetra-1)) > tol6) then
458      ! found a new series
459      jalltetra = jalltetra + 1
460      tetra%tetra_full(:,:,jalltetra) = tetra_full_(:,:,reforder(ialltetra))
461      tetra%tetra_wrap(:,:,jalltetra) = tetra_wrap_(:,:,reforder(ialltetra))
462      tetra%tetra_mult(jalltetra) = 1
463    else
464      ! TODO: add real check that the tetra are equivalent...
465      ! otherwise increment jalltetra here as well, generate new series?
466      tetra%tetra_mult(jalltetra) = tetra%tetra_mult(jalltetra) + tetra_mult_(reforder(ialltetra))
467      !tetra_mult_(reforder(ialltetra)) = 0
468    end if
469  end do
470 
471  ! reset of ntetra for final version after checks and debu
472  tetra%ntetra = ntetra_irred
473 
474  TETRA_DEALLOCATE(tetra_hash)
475  TETRA_DEALLOCATE(reforder)
476  TETRA_DEALLOCATE(irred_itetra)
477  TETRA_DEALLOCATE(tetra_full_)
478  TETRA_DEALLOCATE(tetra_mult_)
479  TETRA_DEALLOCATE(tetra_wrap_)
480 
481  ! Create mapping between the irreducible k-points
482  ! and all the tetrahedron contributing with some weight
483  nkpt_ibz = maxval(indkpt)
484 
485  ! 1. First we count what is the maximum number of distinct tetrahedra that each k-point contains
486  TETRA_ALLOCATE(tetra%ibz_tetra_count,(nkpt_ibz))
487  tetra%ibz_tetra_count(:) = 0
488 
489  ! Count max tetra contributing
490  do ii=1,tetra%ntetra
491    ! Here we need the original ordering to reference the correct irred kpoints
492    ind_ibz(:) = tetra%tetra_full(:,1,ii)
493    ! count max tetra contributing
494    do jj=1,4
495      ikibz = ind_ibz(jj)
496      if (ikibz > nkpt_ibz) cycle
497      tetra%ibz_tetra_count(ikibz) = tetra%ibz_tetra_count(ikibz) + 1
498    end do
499  end do
500 
501  ! 2. Then we build mapping of ikbz to tetra
502  TETRA_ALLOCATE(tetra%ibz_tetra_mapping,(nkpt_ibz,maxval(tetra%ibz_tetra_count)))
503  tetra%ibz_tetra_count(:) = 0
504  do ii=1,tetra%ntetra
505    ! Here we need the original ordering to reference the correct irred kpoints
506    ind_ibz(:) = tetra%tetra_full(:,1,ii)
507    ! Use the counter to move pointer and then fill index
508    do jj=1,4
509      ikibz = ind_ibz(jj)
510      if (ikibz > nkpt_ibz) cycle
511      ! avoid putting the same index twice
512      if (tetra%ibz_tetra_count(ikibz) > 0) then
513        if (tetra%ibz_tetra_mapping(ikibz,tetra%ibz_tetra_count(ikibz)) == ii) cycle
514      end if
515      tetra%ibz_tetra_count(ikibz) = tetra%ibz_tetra_count(ikibz) + 1
516      tetra%ibz_tetra_mapping(ikibz,tetra%ibz_tetra_count(ikibz)) = ii
517    end do
518  end do
519 
520  !call cpu_time(cpu_stop)
521  !write(*,*)"tetra_init 2nd part:", cpu_stop - cpu_start
522  !cpu_start = cpu_stop
523 
524 end subroutine init_tetra

m_tetrahedron/sort_tetra [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

  sort_tetra

FUNCTION

  Sort double precision array list(n) into ascending numerical order using Heapsort
  algorithm, while making corresponding rearrangement of the integer
  array iperm. Consider that two double precision numbers
  within tolerance tol are equal.

INPUTS

  n        intent(in)    dimension of the list
  tol      intent(in)    numbers within tolerance are equal
  list(n)  intent(inout) list of double precision numbers to be sorted
  iperm(n) intent(inout) iperm(i)=i (very important)

OUTPUT

  list(n)  sorted list
  iperm(n) index of permutation given the right ascending order

SOURCE

1298 subroutine sort_tetra(n,list,iperm,tol)
1299 
1300  integer, intent(in) :: n
1301  integer, intent(inout) :: iperm(n)
1302  real(dp), intent(inout) :: list(n)
1303  real(dp), intent(in) :: tol
1304 
1305  integer :: l,ir,iap,i,j
1306  real(dp) :: ap
1307  character(len=500) :: msg
1308 
1309  if (n==1) then
1310    ! Accomodate case of array of length 1: already sorted!
1311    return
1312  else if (n<1) then
1313   ! Should not call with n<1
1314   write(msg,1000) n
1315   1000  format(/,' sort_tetra has been called with array length n=',i12,/, &
1316 &  ' having a value less than 1. This is not allowed.')
1317   TETRA_ERROR(msg)
1318 
1319  else ! n>1
1320 
1321   ! Conduct the usual sort
1322   l=n/2+1
1323   ir=n
1324 
1325   do   ! Infinite do-loop
1326    if (l>1) then
1327     l=l-1
1328     ap=list(l)
1329     iap=iperm(l)
1330 
1331    else ! l<=1
1332     ap=list(ir)
1333     iap=iperm(ir)
1334     list(ir)=list(1)
1335     iperm(ir)=iperm(1)
1336     ir=ir-1
1337 
1338     if (ir==1) then
1339      list(1)=ap
1340      iperm(1)=iap
1341      exit   ! This is the end of this algorithm
1342     end if
1343    end if ! l>1
1344 
1345    i=l
1346    j=l+l
1347 
1348    do while (j<=ir)
1349     if (j<ir) then
1350      if ( list(j)<list(j+1)-tol .or.  &
1351 &        (list(j)<list(j+1)+tol.and.iperm(j)<iperm(j+1))) j=j+1
1352     endif
1353     if (ap<list(j)-tol .or. (ap<list(j)+tol.and.iap<iperm(j))) then
1354      list(i)=list(j)
1355      iperm(i)=iperm(j)
1356      i=j
1357      j=j+j
1358     else
1359      j=ir+1
1360     end if
1361    enddo
1362 
1363    list(i)=ap
1364    iperm(i)=iap
1365 
1366   enddo ! End infinite do-loop
1367 
1368  end if ! n>1
1369 
1370 end subroutine sort_tetra

m_tetrahedron/split_work [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

  split_work

FUNCTION

  Splits the number of tasks, ntasks, among nprocs processors. Used for the MPI parallelization of simple loops.

INPUTS

  ntasks=number of tasks
  comm=MPI communicator.

OUTPUT

  nprocs=Number of MPI processes in the communicator.
  my_start,my_stop= indices defining the initial and final task for this processor
  ierr=Exit status.

NOTES

  If nprocs>ntasks then :
    my_start=ntasks+1
    my_stop=ntask

  In this particular case, loops of the form

  do ii=my_start,my_stop
   ...
  end do

  are not executed. Moreover allocation such as foo(my_start:my_stop) will generate a zero-sized array.

SOURCE

1427 subroutine split_work(ntasks,comm,nprocs,my_start,my_stop,ierr)
1428 
1429 !Arguments ------------------------------------
1430  integer,intent(in)  :: ntasks,comm
1431  integer,intent(out) :: nprocs,my_start,my_stop,ierr
1432 
1433 !Local variables-------------------------------
1434  integer :: res,my_rank,block_p1,block,mpierr
1435 
1436 ! *************************************************************************
1437 
1438  nprocs = 1; my_start = 1; my_stop = ntasks; ierr = 1
1439 #ifdef HAVE_MPI
1440  call MPI_COMM_SIZE(comm,nprocs,mpierr); if (mpierr /= MPI_SUCCESS) return
1441  call MPI_COMM_RANK(comm,my_rank,mpierr); if (mpierr /= MPI_SUCCESS) return
1442 
1443  block   = ntasks/nprocs
1444  res     = MOD(ntasks,nprocs)
1445  block_p1= block+1
1446 
1447  if (my_rank<res) then
1448    my_start =  my_rank   *block_p1+1
1449    my_stop  = (my_rank+1)*block_p1
1450  else
1451    my_start = res*block_p1 + (my_rank-res  )*block + 1
1452    my_stop  = res*block_p1 + (my_rank-res+1)*block
1453  end if
1454 #endif
1455  ierr = 0
1456 
1457 end subroutine split_work

m_tetrahedron/t_tetrahedron [ Types ]

[ Top ] [ m_tetrahedron ] [ Types ]

NAME

 t_tetrahedron

FUNCTION

 tetrahedron geometry object

SOURCE

 71 type, public :: t_tetrahedron
 72 
 73   integer :: ntetra = 0
 74   ! Number of tetrahedra
 75 
 76   real(dp)  :: vv
 77   ! volume of the tetrahedra
 78 
 79   real(dp) :: klatt(3, 3)
 80   ! reciprocal of lattice vectors for full kpoint grid
 81 
 82   integer,allocatable :: tetra_full(:,:,:)
 83   !(4,2,ntetra)
 84   ! For each tetra
 85   !   (:,1,itetra) indices of the vertex in IBZ (symmetrical image)
 86   !   (:,2,itetra) indices of the vertexes in the BZ
 87 
 88   integer,allocatable :: tetra_mult(:)
 89   !(ntetra)
 90   ! multiplicity of each irred tetrahedron
 91 
 92   integer,allocatable :: tetra_wrap(:,:,:)
 93   !(3,4,ntetra)
 94   ! flag to wrap tetrahedron summit into IBZ
 95 
 96   integer,allocatable :: ibz_tetra_count(:)
 97   ! ibz_tetra_mapping(nkpt_ibz)
 98   ! Number of tetrahedra associated to a point in the IBZ.
 99 
100   integer,allocatable :: ibz_tetra_mapping(:,:)
101   ! ibz_tetra_mapping(nkpt_ibz, maxval(tetra%ibz_tetra_count)))
102   ! map ikbz to tetra index.
103 
104 end type t_tetrahedron
105 
106 public :: init_tetra               ! Initialize the object
107                                    ! See also the high-level interface tetra_from_kptrlatt provided by m_kpts.
108 public :: get_tetra_weight         ! Calculate integration weights and their derivatives. shape (nkpt, nene).
109 public :: tetra_blochl_weights     ! Same as in get_tetra_weight but weights have shape (nene, nkpt).
110 public :: get_dbl_tetra_weight     ! Calculate integration weights for double tetrahedron integration of delta functions.
111                                    ! (NB these correspond to the derivative terms in normal tetrahedron).
112 public :: destroy_tetra            ! Free memory.
113 public :: tetra_write              ! Write text file (XML format) with tetra info.
114 public :: tetralib_has_mpi         ! Return True if the library has been compiled with MPI support.
115 public :: tetra_get_onewk          ! Calculate integration weights and their derivatives for a single k-point in the IBZ.
116 public :: tetra_get_onewk_wvals    ! Similar to tetra_get_onewk_wvalsa but receives arbitrary list of frequency points.
117 public :: tetra_get_onetetra_wvals ! Get weights for one tetrahedra with arbitrary list of frequency points

m_tetrahedron/tetra_blochl_weights [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

 tetra_blochl_weights

FUNCTION

 calculate integration weights and their derivatives from Blochl et al PRB 49 16223 [[cite:Bloechl1994a]]
 Same API as get_tetra_weight but output weights here have shape (nene, nkpt)

SOURCE

689 subroutine tetra_blochl_weights(tetra,eigen_in,enemin,enemax,max_occ,nene,nkpt,&
690   bcorr,tweight_t,dtweightde_t,comm)
691 
692 !Arguments ------------------------------------
693 !scalars
694  integer,intent(in) :: nene,nkpt,bcorr,comm
695  type(t_tetrahedron), intent(in) :: tetra
696  real(dp) ,intent(in) :: enemax,enemin,max_occ
697 !arrays
698  real(dp) ,intent(in) :: eigen_in(nkpt)
699  real(dp) ,intent(out) :: dtweightde_t(nene,nkpt),tweight_t(nene,nkpt)
700 
701 !Local variables-------------------------------
702 !scalars
703  integer :: itetra,nprocs,my_start,my_stop,ierr,ii
704 !arrays
705  integer :: ind_ibz(4)
706  real(dp) :: eigen_1tetra(4)
707  real(dp), allocatable :: tweight_tmp(:,:),dtweightde_tmp(:,:),buffer(:,:)
708 
709 ! *********************************************************************
710 
711  TETRA_ALLOCATE(tweight_tmp, (nene, 4))
712  TETRA_ALLOCATE(dtweightde_tmp, (nene, 4))
713  tweight_t = zero; dtweightde_t = zero
714 
715  call split_work(tetra%ntetra, comm, nprocs, my_start, my_stop, ierr)
716  if (ierr /= 0) TETRA_ERROR("Error in MPI layer")
717 
718  ! for each tetrahedron
719  do itetra=my_start,my_stop
720    tweight_tmp = zero
721    dtweightde_tmp = zero
722 
723    ! Here we need the original ordering to reference the correct irred kpoints
724    ind_ibz(:) = tetra%tetra_full(:,1,itetra)
725 
726    ! Sort energies before calling get_onetetra_
727    eigen_1tetra(:) = eigen_in(ind_ibz(:))
728    call sort_tetra(4, eigen_1tetra, ind_ibz, tol14)
729 
730    call get_onetetra_(tetra,itetra,eigen_1tetra,enemin,enemax,max_occ,nene,bcorr,tweight_tmp,dtweightde_tmp)
731 
732    ! NOTE: the following blas calls are not working systematically, or do not give speed ups, strange...
733    !if (nene > 100) then
734    !  do ii=1,4
735    !    call daxpy (nene, 1.d0, tweight_tmp(:,ii), 1, tweight_t(:,ind_ibz(ii)), 1)
736    !  end do
737    !  do ii=1,4
738    !    call daxpy (nene, 1.d0, dtweightde_tmp(:,ii), 1, dtweightde_t(:,ind_ibz(ii)), 1)
739    !  end do
740    !else
741    do ii=1,4
742      tweight_t(:,ind_ibz(ii)) = tweight_t(:,ind_ibz(ii)) + tweight_tmp(:,ii)
743    end do
744    do ii=1,4
745      dtweightde_t(:,ind_ibz(ii)) = dtweightde_t(:,ind_ibz(ii)) + dtweightde_tmp(:,ii)
746    end do
747    !end if
748  end do ! itetra
749 
750  TETRA_DEALLOCATE(tweight_tmp)
751  TETRA_DEALLOCATE(dtweightde_tmp)
752 
753  if (nprocs > 1) then
754 #ifdef HAVE_MPI
755    TETRA_ALLOCATE(buffer, (nene, nkpt))
756    call MPI_ALLREDUCE(tweight_t,buffer,nene*nkpt,MPI_DOUBLE_PRECISION,MPI_SUM,comm,ierr)
757    tweight_t = buffer
758 
759    call MPI_ALLREDUCE(dtweightde_t,buffer,nene*nkpt,MPI_DOUBLE_PRECISION,MPI_SUM,comm,ierr)
760    dtweightde_t = buffer
761    TETRA_DEALLOCATE(buffer)
762 #endif
763  end if
764 
765 end subroutine tetra_blochl_weights

m_tetrahedron/tetra_get_onetetra_wvals [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

 tetra_get_onetetra_wvals

FUNCTION

 Calculate integration weights and their derivatives for a single k-point in the IBZ.

INPUTS

 tetra<t_tetrahedron>=Object with tables for tetrahedron method.
 ik_ibz=Index of the k-point in the IBZ array
 bcorr=1 to include Blochl correction else 0.
 nw=number of energies in wvals
 nibz=number of irreducible kpoints
 wvals(nw)=Frequency points.
 eigen_ibz(nkibz)=eigenenergies for each k point
 [wtol]: If present, frequency points that differ by less that wtol are treated as equivalent.
  and the tetrahedron integration is performed only once per frequency point.

OUTPUT

  weights(nw,2) = integration weights for
    Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
    for a given (band, k-point, spin).

SOURCE

1974 subroutine tetra_get_onetetra_wvals(tetra, itetra, eigen_1tetra, bcorr, nw, wvals, weights, wtol)
1975 
1976 !Arguments ------------------------------------
1977 !scalars
1978  integer,intent(in) :: nw,bcorr
1979  real(dp), optional, intent(in) :: wtol
1980  type(t_tetrahedron), intent(in) :: tetra
1981 !arrays
1982  real(dp),intent(in) :: wvals(nw)
1983  real(dp),intent(out) :: weights(nw, 2, 4)
1984 
1985 !Local variables-------------------------------
1986 !scalars
1987  !integer,save :: done = 0
1988  integer,parameter :: nene3=3
1989  integer :: itetra,ii,idx,iw,ie
1990  integer :: ind(4)
1991  logical :: samew
1992  real(dp),parameter :: max_occ1 = one
1993  real(dp) :: enemin, enemax
1994 !arrays
1995  real(dp) :: theta_tmp(nene3,4), delta_tmp(nene3,4), eigen_1tetra(4)
1996 
1997 ! *********************************************************************
1998 
1999  ind = [1,2,3,4]
2000  call sort_tetra(4, eigen_1tetra, ind, tol14)
2001  weights = 0
2002 
2003  !for all the frequencies
2004  do iw=1,nw
2005    samew = .False.
2006    if (present(wtol)) then
2007      if (iw > 1) samew = abs(wvals(iw) - wvals(iw - 1)) < wtol
2008    end if
2009    if (.not. samew) then
2010      enemin = wvals(iw) - 0.01
2011      enemax = wvals(iw) + 0.01
2012      ie = nene3 / 2 + 1
2013      call get_onetetra_(tetra, itetra, eigen_1tetra, enemin, enemax, max_occ1, nene3, bcorr, &
2014         theta_tmp, delta_tmp)
2015    end if
2016 
2017    ! Accumulate contributions to ik_ibz (there might be multiple vertexes that map onto ik_ibz)
2018    do ii=1,4
2019      idx = ind(ii)
2020      weights(iw, 1, idx) = weights(iw, 1, idx) + delta_tmp(ie, ii)
2021      weights(iw, 2, idx) = weights(iw, 2, idx) + theta_tmp(ie, ii)
2022    end do
2023  end do !iw
2024 
2025 end subroutine tetra_get_onetetra_wvals

m_tetrahedron/tetra_get_onewk [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

 tetra_get_onewk

FUNCTION

 Calculate integration weights and their derivatives for a single k-point in the IBZ.

INPUTS

 tetra<t_tetrahedron>=Object with tables for tetrahedron method.
 ik_ibz=Index of the k-point in the IBZ array
 bcorr=1 to include Blochl correction else 0.
 nene=number of energies for DOS
 nibz=number of irreducible kpoints
 eigen_ibz(nkibz)=eigenenergies for each k point
 enemin=minimal energy for DOS
 enemax=maximal energy for DOS
 max_occ=maximal occupation number (2 for nsppol=1, 1 for nsppol=2)

OUTPUT

  weights(nene,2) = integration weights for
    Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
    for a given (band, k-point, spin).

SOURCE

1807 subroutine tetra_get_onewk(tetra,ik_ibz,bcorr,nene,nkibz,eig_ibz,enemin,enemax,max_occ,weights)
1808 
1809 !Arguments ------------------------------------
1810 !scalars
1811  integer,intent(in) :: ik_ibz,nene,nkibz,bcorr
1812  type(t_tetrahedron), intent(in) :: tetra
1813  real(dp) ,intent(in) :: enemin,enemax,max_occ
1814 !arrays
1815  real(dp),intent(in) :: eig_ibz(nkibz)
1816  real(dp),intent(out) :: weights(nene,2)
1817 
1818 !Local variables-------------------------------
1819 !scalars
1820  integer :: itetra,ii
1821 !arrays
1822  integer :: ind_ibz(4)
1823  real(dp) :: tweight_tmp(nene,4),dtweightde_tmp(nene,4),eigen_1tetra(4)
1824 
1825 ! *********************************************************************
1826 
1827  weights = zero
1828 
1829  ! For each tetrahedron
1830  do itetra=1,tetra%ntetra
1831 
1832    ! Here we need the original ordering to reference the correct irred kpoints
1833    ind_ibz(:) = tetra%tetra_full(:,1,itetra)
1834    ! Cycle if this tetra does not contribute to this k-point.
1835    if (all(ind_ibz /= ik_ibz)) cycle
1836 
1837    ! Sort energies before calling get_onetetra_
1838    eigen_1tetra(:) = eig_ibz(ind_ibz(:))
1839    call sort_tetra(4, eigen_1tetra, ind_ibz, tol14)
1840 
1841    call get_onetetra_(tetra, itetra, eigen_1tetra, enemin, enemax, max_occ, nene, bcorr, &
1842      tweight_tmp, dtweightde_tmp)
1843 
1844    ! Accumulate contributions to ik_ibz (there might be multiple vertexes that map onto ik_ibz)
1845    do ii=1,4
1846      if (ind_ibz(ii) == ik_ibz) then
1847        weights(:,1) = weights(:,1) + dtweightde_tmp(:,ii)
1848        weights(:,2) = weights(:,2) + tweight_tmp(:,ii)
1849      end if
1850    end do
1851  end do ! itetra
1852 
1853 end subroutine tetra_get_onewk

m_tetrahedron/tetra_get_onewk_wvals [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

 tetra_get_onewk_wvals

FUNCTION

 Calculate integration weights and their derivatives for a single k-point in the IBZ.

INPUTS

 tetra<t_tetrahedron>=Object with tables for tetrahedron method.
 ik_ibz=Index of the k-point in the IBZ array
 bcorr=1 to include Blochl correction else 0.
 nw=number of energies in wvals
 nibz=number of irreducible kpoints
 wvals(nw)=Frequency points.
 eigen_ibz(nkibz)=eigenenergies for each k point
 [wtol]: If present, frequency points that differ by less that wtol are treated as equivalent.
  and the tetrahedron integration is performed only once per frequency point.

OUTPUT

  weights(nw,2) = integration weights for
    Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
    for a given (band, k-point, spin).

SOURCE

1883 subroutine tetra_get_onewk_wvals(tetra, ik_ibz, bcorr, nw, wvals, nkibz, eig_ibz, weights, wtol)
1884 
1885 !Arguments ------------------------------------
1886 !scalars
1887  integer,intent(in) :: ik_ibz,nw,nkibz,bcorr
1888  real(dp), optional, intent(in) :: wtol
1889  type(t_tetrahedron), intent(in) :: tetra
1890 !arrays
1891  real(dp),intent(in) :: wvals(nw)
1892  real(dp),intent(in) :: eig_ibz(nkibz)
1893  real(dp),intent(out) :: weights(nw, 2)
1894 
1895 !Local variables-------------------------------
1896 !scalars
1897  !integer,save :: done = 0
1898  integer,parameter :: nene=3
1899  integer :: itetra,ii,jj,iw,ie
1900  logical :: samew
1901  real(dp),parameter :: max_occ1 = one
1902  real(dp) :: enemin, enemax
1903 !arrays
1904  integer :: ind_ibz(4)
1905  real(dp) :: theta_tmp(nene,4), delta_tmp(nene,4), eigen_1tetra(4)
1906 
1907 ! *********************************************************************
1908 
1909  weights = zero
1910 
1911  ! For each tetrahedron
1912  do jj=1,tetra%ibz_tetra_count(ik_ibz)
1913    itetra = tetra%ibz_tetra_mapping(ik_ibz,jj)
1914 
1915    ! Here we need the original ordering to reference the correct irred kpoints
1916    ind_ibz(:) = tetra%tetra_full(:,1,itetra)
1917 
1918    ! Sort energies before calling get_onetetra_
1919    eigen_1tetra(:) = eig_ibz(ind_ibz(:))
1920    call sort_tetra(4, eigen_1tetra, ind_ibz, tol14)
1921 
1922    do iw=1,nw
1923      samew = .False.
1924      if (present(wtol)) then
1925        if (iw > 1) samew = abs(wvals(iw) - wvals(iw - 1)) < wtol
1926      end if
1927      if (.not. samew) then
1928          enemin = wvals(iw) - 0.01; enemax = wvals(iw) + 0.01
1929          ie = nene / 2 + 1
1930          call get_onetetra_(tetra, itetra, eigen_1tetra, enemin, enemax, max_occ1, nene, bcorr, &
1931             theta_tmp, delta_tmp)
1932      end if
1933 
1934      ! Accumulate contributions to ik_ibz (there might be multiple vertexes that map onto ik_ibz)
1935      do ii=1,4
1936        if (ind_ibz(ii) == ik_ibz) then
1937          weights(iw, 1) = weights(iw, 1) + delta_tmp(ie, ii)
1938          weights(iw, 2) = weights(iw, 2) + theta_tmp(ie, ii)
1939        end if
1940      end do
1941    end do ! iw
1942  end do ! itetra
1943 
1944 end subroutine tetra_get_onewk_wvals

m_tetrahedron/tetra_write [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

 tetra_write

FUNCTION

  Write text file with tetra info.

INPUTS

  tetra<t_tetrahedron>=tetrahedron geometry object
  nkibz=Number of k-points in the IBZ used to generate tetra
  kibz(3,nkibz)=Reduced coordinates of the IBZ
  path=Name of output file

OUTPUT

  Output is written to file.

SOURCE

547 subroutine tetra_write(tetra, nkibz, kibz, path)
548 
549 !Arguments ------------------------------------
550 !scalars
551  integer,intent(in) :: nkibz
552  character(len=*),intent(in) :: path
553  type(t_tetrahedron),intent(in) :: tetra
554 !arrays
555  real(dp),intent(in) :: kibz(3,nkibz)
556 
557 !Local variables-------------------------------
558  integer,parameter :: version=1
559  integer :: ik,it,unt
560 #ifdef HAVE_LIBTETRA_ABINIT
561  character(len=500) :: msg
562 #endif
563 
564 ! *********************************************************************
565 
566 #ifdef HAVE_LIBTETRA_ABINIT
567  if (open_file(file=trim(path),iomsg=msg,newunit=unt,form="formatted",status="unknown",action="write")/=0) then
568    TETRA_ERROR(msg)
569  end if
570 #else
571  open(file=trim(path),newunit=unt,form="formatted",status="unknown",action="write")
572 #endif
573 
574  write(unt,*)version, " # version number"
575 
576  ! Write IBZ
577  write(unt,*)nkibz, " # number of k-points in the IBZ"
578  write(unt,"(a)")"<irreducible_zone>"
579  do ik=1,nkibz
580    write(unt,"(3es22.12)") kibz(:,ik)
581  end do
582  write(unt,"(a)")"</irreducible_zone>"
583 
584  ! Write tetra info
585  write(unt,"(i0,a)")tetra%ntetra, " # number of tetrahedra"
586  write(unt,"(es22.12,a)")tetra%vv, " # tetrahedron volume"
587 
588  write(unt,"(a)")"<tetra_full>"
589  do it=1,tetra%ntetra
590    write(unt,"(8(i0,1x))")tetra%tetra_full(:,:,it)
591  end do
592  write(unt,"(a)")"</tetra_full>"
593 
594  write(unt,"(a)")"<tetra_mult>"
595  do it=1,tetra%ntetra
596    write(unt,"(i0)")tetra%tetra_mult(it)
597  end do
598  write(unt,"(a)")"</tetra_mult>"
599 
600  write(unt,"(a)")"<tetra_wrap>"
601  do it=1,tetra%ntetra
602    write(unt,"(12(i0,1x))")tetra%tetra_wrap(:,:,it)
603  end do
604  write(unt,"(a)")"</tetra_wrap>"
605 
606  close(unt)
607 
608 end subroutine tetra_write

m_tetrahedron/tetralib_has_mpi [ Functions ]

[ Top ] [ m_tetrahedron ] [ Functions ]

NAME

 tetralib_has_mpi

FUNCTION

 Return True if library has been compiled with MPI support

SOURCE

1384 logical function tetralib_has_mpi() result(ans)
1385 
1386   ans = .False.
1387 #ifdef HAVE_MPI
1388   ans = .True.
1389 #endif
1390 
1391 end function tetralib_has_mpi