TABLE OF CONTENTS


ABINIT/m_exc_diago [ Modules ]

[ Top ] [ Modules ]

NAME

 m_exc_diago

FUNCTION

COPYRIGHT

 Copyright (C) 2009-2024 ABINIT and EXC groups (L.Reining, V.Olevano, F.Sottile, S.Albrecht, G.Onida, M.Giantomassi)
  This file is distributed under the terms of the
  GNU General Public License, see ~abinit/COPYING
  or http://www.gnu.org/copyleft/gpl.txt .

SOURCE

15 #if defined HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18 
19 #include "abi_common.h"
20 
21 MODULE m_exc_diago
22 
23  use defs_basis
24  use m_bs_defs
25  use m_abicore
26  use m_errors
27  use m_xmpi
28 #if defined HAVE_MPI2
29  use mpi
30 #endif
31  use m_hdr
32  use m_sort
33  use m_slk
34 
35  use defs_datatypes,    only : pseudopotential_type, ebands_t
36  use m_io_tools,        only : open_file
37  use m_fstrings,        only : int2char4
38  use m_numeric_tools,   only : print_arr, hermitianize
39  !use m_slk,             only : matrix_scalapack, processor_scalapack
40  use m_crystal,         only : crystal_t
41  use m_kpts,            only : listkk
42  use m_bz_mesh,         only : kmesh_t
43  use m_ebands,          only : ebands_report_gap
44  use m_eprenorms,       only : eprenorms_t
45  use m_wfd,             only : wfdgw_t
46  use m_paw_hr,          only : pawhur_t
47  use m_pawtab,          only : pawtab_type
48  use m_exc_itdiago,     only : exc_iterative_diago
49  use m_hide_lapack,     only : xheev, xheevx, xgeev, xhegvx, xginv, xhdp_invert, xhegv
50  use m_hide_blas,       only : xdotc, xgemm
51  use m_bse_io,          only : exc_fullh_from_blocks, offset_in_file, rrs_of_glob, ccs_of_glob, &
52 &                              exc_read_bshdr, exc_skip_bshdr_mpio, exc_read_rblock_fio
53  use m_exc_spectra,     only : build_spectra
54 
55  implicit none
56 
57  private
58 
59 #if defined HAVE_MPI1
60  include 'mpif.h'
61 #endif
62 
63 !#define DEV_MG_DEBUG_THIS
64 
65  public ::  exc_diago_driver ! Driver routine for the direct diagonalization of the BSE Hamiltonian (main entry point)

m_exc_diago/exc_diago_coupling [ Functions ]

[ Top ] [ m_exc_diago ] [ Functions ]

NAME

  exc_diago_coupling

FUNCTION

  Calculate excitonic eigenvalues and eigenvectors by performing a direct diagonalization.
  of the non Hermitian excitonic Hamiltoninan (resonant + coupling).

INPUTS

  bseig_fname=The name of the output file.
  Bsp
    neh=Rank of the resonant block of the Hamiltoninan (equal to the rank of the coupling part)
  comm=MPI communicator.
  BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.

OUTPUT

  Excitonic eigenvectors and eigenvalues are written on file BS_files%out_eig.

SOURCE

 807 subroutine exc_diago_coupling(Bsp,BS_files,Hdr_bse,prtvol,comm)
 808 
 809 !Arguments ------------------------------------
 810 !scalars
 811  integer,intent(in) :: comm,prtvol
 812  type(excfiles),intent(in) :: BS_files
 813  type(excparam),intent(in) :: BSp
 814  type(Hdr_type),intent(in) :: Hdr_bse
 815 
 816 !Local variables ------------------------------
 817 !scalars
 818  integer,parameter :: master=0,ldvl=1
 819  integer(i8b) :: bsize_ham
 820  integer :: ii,exc_size,hreso_unt,hcoup_unt,eig_unt,nsppol,nstates
 821  integer :: bsz,block,bs1,bs2,jj
 822  integer :: fform,row_sign
 823  integer :: mi,it,nprocs,my_rank !itp
 824  integer :: nene_printed,ierr
 825  real(dp) :: exc_gap,exc_maxene,temp
 826  logical :: diago_is_real,do_full_diago
 827  logical :: do_ep_lifetime
 828  character(len=500) :: msg
 829  character(len=fnlen) :: hreso_fname,hcoup_fname,bseig_fname
 830 !arrays
 831  complex(dpc),allocatable :: exc_ham(:,:),exc_rvect(:,:),exc_ene(:),ovlp(:,:)
 832  complex(dpc),allocatable :: cbuff(:,:)
 833  complex(dpc) :: vl_dpc(ldvl,1)
 834 
 835 !************************************************************************
 836 
 837  my_rank = xmpi_comm_rank(comm); nprocs  = xmpi_comm_size(comm)
 838 
 839  nsppol = Hdr_bse%nsppol
 840  if (nsppol==2) then
 841    ABI_WARNING("nsppol==2 with coupling is still under development")
 842  end if
 843 
 844  if (nprocs > 1) then
 845    ABI_WARNING("Scalapack does not provide ZGEEV, diagonalization is done in sequential!")
 846  end if
 847 
 848  exc_size = 2*SUM(BSp%nreh)
 849  nstates  = BSp%nstates
 850  do_full_diago = (exc_size==nstates)
 851  ABI_CHECK(do_full_diago,"Partial diago not coded yet")
 852 
 853  bseig_fname = BS_files%out_eig
 854  if (BS_files%in_eig /= BSE_NOFILE) then
 855    ABI_ERROR("BS_files%in_eig is defined!")
 856  end if
 857  !
 858  ! Only master performs the diagonalization since ScaLAPACK does not provide the parallel version of ZGEEV.
 859  if (my_rank/=master) GOTO 10
 860 
 861  write(msg,'(a,i0)')' Direct diagonalization of the full excitonic Hamiltonian, Matrix size= ',exc_size
 862  call wrtout([std_out, ab_out], msg)
 863 
 864  bsize_ham = 2*dpc*exc_size**2
 865  write(msg,'(a,f9.2,a)')' Allocating full excitonic Hamiltonian. Memory requested: ',bsize_ham*b2Gb,' Gb. '
 866  call wrtout(std_out, msg)
 867 
 868  ABI_MALLOC_OR_DIE(exc_ham,(exc_size,exc_size), ierr)
 869 
 870  write(msg,'(3a,f8.1,3a,f8.1,a)')&
 871   ' Allocating excitonic eigenvalues and eigenvectors. ',ch10,&
 872   ' Memory-space requested: ',2*dpc*exc_size*b2Gb,' Gb. ',ch10,&
 873   ' Memory-space requested: ',bsize_ham*b2Gb,' Gb. '
 874  call wrtout(std_out, msg)
 875 
 876  ABI_MALLOC_OR_DIE(exc_ene,(exc_size), ierr)
 877 
 878  if (BS_files%in_hreso /= BSE_NOFILE) then
 879    hreso_fname = BS_files%in_hreso
 880  else
 881    hreso_fname = BS_files%out_hreso
 882  end if
 883 
 884  call wrtout(std_out,' Reading resonant excitonic Hamiltonian from '//TRIM(hreso_fname))
 885 
 886  if (open_file(hreso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
 887    ABI_ERROR(msg)
 888  end if
 889  !
 890  ! Read the header and perform consistency checks.
 891  call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
 892  ABI_CHECK(ierr==0,"Wrong header")
 893  !
 894  ! Construct resonant and anti-resonant part of the excitonic Hamiltonian using Hermiticity. File is always in double precision.
 895  ! Fill exc_ham with ( R  0 )
 896  !                   ( 0 -R*)
 897 !BEGINDEBUG
 898  exc_ham = HUGE(one)
 899 !ENDDEBUG
 900 
 901  row_sign=-1; diago_is_real=(.not.BSp%have_complex_ene)
 902  call exc_fullh_from_blocks(hreso_unt,"Resonant",nsppol,row_sign,diago_is_real,BSp%nreh,exc_size,exc_ham)
 903  close(hreso_unt)
 904 
 905  if (BS_files%in_hcoup /= BSE_NOFILE) then
 906    hcoup_fname =  BS_files%in_hcoup
 907  else
 908    hcoup_fname =  BS_files%out_hcoup
 909  end if
 910 
 911  call wrtout(std_out,' Reading coupling excitonic Hamiltonian from '//TRIM(hcoup_fname))
 912  if (open_file(hcoup_fname,msg,newunit=hcoup_unt,form="unformatted",status="old",action="read") /= 0) then
 913    ABI_ERROR(msg)
 914  end if
 915  !
 916  ! Read the header and perform consistency checks.
 917  call exc_read_bshdr(hcoup_unt,Bsp,fform,ierr)
 918  ABI_CHECK(ierr==0,"Wrong header")
 919  !
 920  ! Fill exc_ham with ( 0  C) to have ( R   C )
 921  !                   (-C* 0)         (-C* -R*)
 922  row_sign=-1; diago_is_real=(.not.BSp%have_complex_ene) ! not used here
 923  call exc_fullh_from_blocks(hcoup_unt,"Coupling",nsppol,row_sign,diago_is_real,BSp%nreh,exc_size,exc_ham)
 924 
 925 !BEGINDEBUG
 926  if (ANY(exc_ham==HUGE(one))) then
 927    write(msg,'(a,2(1x,i0))')"There is a bug in exc_fullh_from_blocks",COUNT(exc_ham==HUGE(one)),exc_size**2
 928    ABI_WARNING(msg)
 929    bsz = Bsp%nreh(1)
 930    ABI_MALLOC(cbuff,(bsz,bsz))
 931    block=0
 932    do jj=1,2*nsppol
 933      do ii=1,2*nsppol
 934        block=block+1
 935        bs1 = (ii-1)*bsz+1
 936        bs2 = (jj-1)*bsz+1
 937        cbuff = exc_ham(bs1:bs1+bsz-1,bs2:bs2+bsz-1)
 938        if (ANY(cbuff==HUGE(one))) then
 939          write(std_out,*)" for block ",ii,jj," found ",COUNT(cbuff==HUGE(one))," wrong entries"
 940        end if
 941      end do
 942    end do
 943 
 944    ABI_FREE(cbuff)
 945    ABI_ERROR("Cannot continue")
 946  end if
 947 !ENDDEBUG
 948 
 949  close(hcoup_unt)
 950  !
 951  ! ======================================================
 952  ! ==== Calculate right eigenvectors and eigenvalues ====
 953  ! ======================================================
 954  ABI_MALLOC_OR_DIE(exc_rvect,(exc_size,exc_size), ierr)
 955 
 956  if (do_full_diago) then
 957    call wrtout(std_out,"Complete direct diagonalization with xgeev...")
 958    call xgeev("No_left_eigen","Vectors",exc_size,exc_ham,exc_size,exc_ene,vl_dpc,ldvl,exc_rvect,exc_size)
 959  else
 960    ABI_ERROR("Not implemented error")
 961  end if
 962 
 963  ABI_FREE(exc_ham)
 964 
 965  exc_gap    = MINVAL(ABS(DBLE (exc_ene(1:nstates))))
 966  exc_maxene = MAXVAL(ABS(DBLE (exc_ene(1:nstates))))
 967  temp       = MAXVAL(ABS(AIMAG(exc_ene(1:nstates))))
 968 
 969  write(msg,'(2(a,f7.2,2a),a,es9.2,2a)')&
 970   " First excitonic eigenvalue: ",exc_gap*Ha_eV,   " [eV].",ch10,&
 971   " Last  excitonic eigenvalue: ",exc_maxene*Ha_eV," [eV].",ch10,&
 972   " Largest imaginary part:     ",temp*Ha_eV,      " [eV] ",ch10
 973  call wrtout([std_out, ab_out], msg)
 974 
 975  nene_printed = MIN(32*nsppol,nstates); if (prtvol>10) nene_printed = nstates
 976 
 977  ! This is not portable as the the eigenvalues calculated by ZGEEV are not sorted.
 978  ! Even two subsequent calculations with the same input on the same machine
 979  ! might produce different orderings. Might sort the eigenvalues though, just for printing.
 980 
 981  write(msg,'(a,i0)')' Complex excitonic eigenvalues in eV up to n= ',nene_printed
 982  call wrtout(std_out,msg)
 983 
 984  do it=0,(nene_printed-1)/4
 985    write(msg,'(8f10.5)') ( exc_ene(ii)*Ha_eV, ii=1+it*4,MIN(it*4+4,nene_printed) )
 986    call wrtout(std_out,msg)
 987  end do
 988 
 989  call wrtout(std_out,ch10//" Writing eigenvalues and eigenvectors on file "//TRIM(bseig_fname))
 990 
 991  if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
 992    ABI_ERROR(msg)
 993  end if
 994 
 995 !YG : new version with lifetime
 996  do_ep_lifetime = .FALSE.
 997  write(eig_unt) do_ep_lifetime
 998 
 999  write(eig_unt)exc_size,nstates
1000  write(eig_unt)CMPLX(exc_ene(1:nstates),kind=dpc)
1001  do mi=1,nstates
1002    write(eig_unt) exc_rvect(:,mi)
1003  end do
1004 
1005  ABI_FREE(exc_ene)
1006 
1007  ABI_MALLOC_OR_DIE(ovlp,(nstates,nstates), ierr)
1008 
1009  call wrtout(std_out,' Calculating overlap matrix... ')
1010 
1011  !do itp=1,nstates
1012  !  do it=1,nstates
1013  !    ovlp(it,itp) = xdotc(exc_size,exc_rvect(:,it),1,exc_rvect(:,itp),1)
1014  !  end do
1015  !end do
1016  call xgemm("C","N",exc_size,nstates,nstates,cone,exc_rvect,exc_size,exc_rvect,exc_size,czero,ovlp,nstates)
1017  ABI_FREE(exc_rvect)
1018 
1019  call wrtout(std_out," Inverting overlap matrix... ")
1020 
1021  ! Version for generic complex matrix.
1022  !call xginv(ovlp,exc_size)
1023 
1024  ! The overlap is Hermitian definite positive.
1025  call xhdp_invert("Upper",ovlp,nstates)
1026  call hermitianize(ovlp,"Upper")
1027 
1028  call wrtout(std_out,' Writing overlap matrix S^-1 on file: '//TRIM(bseig_fname))
1029 
1030  do it=1,nstates
1031    write(eig_unt) CMPLX(ovlp(:,it),kind=dpc)
1032  end do
1033 
1034  ABI_FREE(ovlp)
1035 
1036  close(eig_unt)
1037 
1038 10 call xmpi_barrier(comm)
1039 
1040 end subroutine exc_diago_coupling

m_exc_diago/exc_diago_coupling_hegv [ Functions ]

[ Top ] [ m_exc_diago ] [ Functions ]

NAME

  exc_diago_coupling_hegv

FUNCTION

  Calculate excitonic eigenvalues and eigenvectors by performing a direct diagonalization.
  of the non Hermitian excitonic Hamiltonian (resonant + coupling).

INPUTS

  bseig_fname=The name of the output file.
  Bsp
    neh=Rank of the resonant block of the Hamiltoninan (equal to the rank of the coupling part)
  comm=MPI communicator.
  BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.

OUTPUT

  Excitonic eigenvectors and eigenvalues are written to file BS_files%out_eig.

SOURCE

1065 subroutine exc_diago_coupling_hegv(Bsp,BS_files,Hdr_bse,prtvol,comm)
1066 
1067 !Arguments ------------------------------------
1068 !scalars
1069  integer,intent(in) :: comm,prtvol
1070  type(excparam),intent(in) :: BSp
1071  type(excfiles),intent(in) :: BS_files
1072  type(Hdr_type),intent(in) :: Hdr_bse
1073 
1074 !Local variables ------------------------------
1075 !scalars
1076  integer,parameter :: master=0
1077  integer(i8b) :: bsize_ham
1078  integer :: itype,il,iu,spin,row1,row2,pad_r1,pad_r2,neh1,neh2
1079  integer :: ii,exc_size,hreso_unt,hcoup_unt,eig_unt
1080  integer :: fform,neig_found,nstates
1081  integer :: mi,it,nprocs,my_rank
1082  integer :: nene_printed,nsppol,row_sign,ierr
1083  real(dp) :: exc_gap,exc_maxene,abstol,vl,vu
1084  character(len=500) :: msg
1085  character(len=fnlen) :: reso_fname,coup_fname,bseig_fname
1086  logical :: use_scalapack,do_full_diago,diago_is_real
1087  logical :: do_ep_lifetime
1088 !arrays
1089  real(dp),allocatable :: exc_ene(:) !,test_ene(:)
1090  complex(dpc),allocatable :: exc_ham(:,:),exc_rvect(:,:),fmat(:,:),ovlp(:,:)
1091 #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
1092  integer,parameter :: istwfk1=1
1093  integer :: amode,mpi_fh,tbloc,mene_found,mpi_err,my_nel,nsblocks
1094  integer :: iloc,jloc,iglob,jglob,etype,slk_mask_type,offset_err,el,rrs_kind,ccs_kind
1095  !integer :: max_r,max_c
1096  integer(XMPI_OFFSET_KIND) :: ehdr_offset,fmarker,my_offset
1097  integer :: gsub(2,2)
1098  logical,parameter :: is_fortran_file=.TRUE.
1099  complex(dpc) :: ctmp
1100  integer,allocatable :: sub_block(:,:,:)
1101  integer,pointer :: myel2loc(:,:)
1102  complex(dpc),allocatable :: tmp_cbuffer(:)
1103  character(50) :: uplo
1104  real(dp),external :: PDLAMCH
1105  type(matrix_scalapack)    :: Slk_F,Slk_Hbar,Slk_vec,Slk_ovlp !,Slk_tmp
1106  type(processor_scalapack) :: Slk_processor
1107 #endif
1108 
1109 !************************************************************************
1110 
1111  my_rank = xmpi_comm_rank(comm); nprocs  = xmpi_comm_size(comm)
1112 
1113  nsppol = Hdr_bse%nsppol
1114  if (nsppol==2) then
1115    ABI_WARNING("nsppol==2 is still under development!")
1116  end if
1117 
1118  neh1 = BSp%nreh(1); neh2=neh1
1119  if (nsppol==2) neh2 = BSp%nreh(2)
1120 
1121  exc_size = 2*SUM(Bsp%nreh)
1122  nstates  = Bsp%nstates
1123  do_full_diago=(nstates==exc_size)
1124 
1125  write(msg,'(a,i0)')'. Direct diagonalization of the full excitonic Hamiltonian, Matrix size= ',exc_size
1126  call wrtout([std_out, ab_out], msg)
1127 
1128  bseig_fname = BS_files%out_eig
1129  if (BS_files%in_eig /= BSE_NOFILE) then
1130    ABI_ERROR("BS_files%in_eig is defined!")
1131  end if
1132 
1133  if (BS_files%in_hreso /= BSE_NOFILE) then
1134    reso_fname = BS_files%in_hreso
1135  else
1136    reso_fname = BS_files%out_hreso
1137  end if
1138  call wrtout(std_out,' Reading resonant excitonic Hamiltonian from '//TRIM(reso_fname))
1139 
1140  if (BS_files%in_hcoup /= BSE_NOFILE) then
1141    coup_fname =  BS_files%in_hcoup
1142  else
1143    coup_fname =  BS_files%out_hcoup
1144  end if
1145  call wrtout(std_out,' Reading coupling excitonic Hamiltonian from '//TRIM(coup_fname))
1146 
1147  ! TODO: Reintegrate SCALAPACK: use new format
1148 ! --- !ERROR
1149 ! src_file: m_exc_diago.F90
1150 ! src_line: 1398
1151 ! mpi_rank: 0
1152 ! message: |
1153 !     SET_VIEW
1154 !     Other I/O error , error stack:
1155 !     ADIO_Set_view(48):  **iobadoverlap displacements of filetype must be in a monotonically nondecreasing order
1156 ! ...
1157 
1158  use_scalapack = .FALSE.
1159 #ifdef HAVE_LINALG_SCALAPACK
1160  ! This is alway false. I use this trick so that the second case below is always compiled
1161  ! to avoid regressions.
1162  use_scalapack = nprocs > 1 .and. nsppol > 5
1163 #endif
1164  !use_scalapack = .FALSE.
1165  !use_scalapack = .TRUE.
1166 
1167  if (.not.use_scalapack .and. my_rank/=master) GOTO 10
1168 
1169  ABI_MALLOC_OR_DIE(exc_ene,(exc_size), ierr)
1170 
1171  SELECT CASE (use_scalapack)
1172 
1173  CASE (.FALSE.)
1174    write(msg,'(a)')". Using LAPACK sequential version to solve FHv = ev with H positive definite. "
1175    call wrtout([std_out, ab_out], msg)
1176 
1177    bsize_ham = 2*dpc*exc_size**2
1178    write(msg,'(a,f9.2,a)')' Allocating full excitonic Hamiltonian. Memory requested: ',2*bsize_ham*b2Gb,' Gb. '
1179    call wrtout(std_out, msg)
1180 
1181    ABI_MALLOC_OR_DIE(exc_ham,(exc_size,exc_size), ierr)
1182    ABI_MALLOC_OR_DIE(fmat,(exc_size,exc_size), ierr)
1183 
1184    write(msg,'(3a,f8.1,3a,f8.1,a)')&
1185     ' Allocating excitonic eigenvalues and eigenvectors. ',ch10,&
1186     ' Memory-space requested: ',2*dpc*exc_size*b2Gb,' Gb. ',ch10,&
1187     ' Memory-space requested: ',bsize_ham*b2Gb,' Gb. '
1188    call wrtout(std_out, msg)
1189 
1190    if (open_file(reso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
1191      ABI_ERROR(msg)
1192    end if
1193    !
1194    ! Read the header and perform consistency checks.
1195    call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
1196    ABI_CHECK(ierr==0,"Wrong header")
1197    !
1198    ! Construct Hbar = ( R   C )
1199    !                  ( C*  R*)
1200    !
1201    row_sign=+1; diago_is_real=(.not.BSp%have_complex_ene)
1202    call exc_fullh_from_blocks(hreso_unt,"Resonant",nsppol,row_sign,diago_is_real,Bsp%nreh,exc_size,exc_ham)
1203    close(hreso_unt)
1204 
1205    if (open_file(coup_fname,msg,newunit=hcoup_unt,form="unformatted",status="old",action="read") /= 0) then
1206      ABI_ERROR(msg)
1207    end if
1208    !
1209    ! Read the header and perform consistency checks.
1210    call exc_read_bshdr(hcoup_unt,Bsp,fform,ierr)
1211    ABI_CHECK(ierr==0,"Wrong header")
1212 
1213    row_sign=+1; diago_is_real=(.not.BSp%have_complex_ene) ! not used here.
1214    call exc_fullh_from_blocks(hcoup_unt,"Coupling",nsppol,row_sign,diago_is_real,Bsp%nreh,exc_size,exc_ham)
1215    close(hcoup_unt)
1216 
1217 !#ifdef DEV_MG_DEBUG_THIS
1218 !write(666)exc_ham
1219 !#endif
1220    !
1221    ! Fill fmat = (1  0)
1222    !             (0 -1)
1223    fmat = czero
1224    do spin=1,nsppol
1225      pad_r1 = (spin-1)*Bsp%nreh(1)
1226      pad_r2 = SUM(Bsp%nreh)
1227      if (spin==2) pad_r2 = pad_r2 + Bsp%nreh(1)
1228      do it=1,Bsp%nreh(spin)
1229        row1 = it + pad_r1
1230        row2 = it + pad_r2
1231        fmat(row1,row1) =  cone
1232        fmat(row2,row2) = -cone
1233      end do
1234    end do
1235    !
1236    ! ==================================================
1237    ! ==== Solve generalized EV problem F H u = e u ====
1238    ! ==================================================
1239    ! The eigenvectors Z are normalized as follows: if ITYPE = 1 or 2, Z**T*B*Z = I; if ITYPE = 3, Z**T*inv(B)*Z = I.
1240    !
1241    itype=2
1242    if (do_full_diago) then
1243      call wrtout(std_out," Full diagonalization with XHEGV... ")
1244      call xhegv(itype,"Vectors","Upper",exc_size,fmat,exc_ham,exc_ene)
1245    else
1246      call wrtout(std_out," Partial diagonalization with XHEGVX... ")
1247      ABI_MALLOC_OR_DIE(exc_rvect,(exc_size,nstates), ierr)
1248      il=1; iu=1; abstol=zero
1249      call xhegvx(itype,"Vectors","All","Upper",exc_size,fmat,exc_ham,vl,vu,il,iu,abstol,neig_found,exc_ene,exc_rvect,exc_size)
1250    end if
1251 
1252    ABI_FREE(exc_ham)
1253 
1254    if (do_full_diago) then
1255      ABI_MALLOC(exc_rvect,(exc_size,nstates))
1256      exc_rvect = fmat(:,1:nstates)
1257    end if
1258 
1259    ABI_FREE(fmat)
1260 
1261    call wrtout(std_out," Writing eigenvalues and eigenvectors on file: "//TRIM(bseig_fname))
1262 
1263    if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
1264      ABI_ERROR(msg)
1265    end if
1266 
1267    do_ep_lifetime = .FALSE.
1268    write(eig_unt) do_ep_lifetime
1269    write(eig_unt) exc_size, nstates
1270    write(eig_unt) CMPLX(exc_ene(1:nstates),kind=dpc)
1271    do mi=1,nstates
1272      write(eig_unt) CMPLX(exc_rvect(:,mi),kind=dpc)
1273    end do
1274 
1275 !#ifdef DEV_MG_DEBUG_THIS
1276 !   write(888)exc_rvect
1277 !   write(888)exc_ene
1278 !#endif
1279 
1280    ABI_MALLOC_OR_DIE(ovlp,(nstates,nstates), ierr)
1281 
1282    call wrtout(std_out,' Calculating overlap matrix...')
1283 
1284    call xgemm("C","N",exc_size,nstates,nstates,cone,exc_rvect,exc_size,exc_rvect,exc_size,czero,ovlp,nstates)
1285    ABI_FREE(exc_rvect)
1286 
1287 !#ifdef DEV_MG_DEBUG_THIS
1288 !write(667)ovlp
1289 !#endif
1290 
1291    call wrtout(std_out," Inverting overlap matrix... ")
1292    !
1293    ! The overlap is Hermitian definite positive.
1294    call xhdp_invert("Upper",ovlp,nstates)
1295    call hermitianize(ovlp,"Upper")
1296 
1297    ! Version for generic complex matrix.
1298    !call xginv(ovlp,nstates)
1299 
1300 !#ifdef DEV_MG_DEBUG_THIS
1301 !write(668,*)ovlp
1302 !#endif
1303 
1304    call wrtout(std_out,' Writing overlap matrix O^-1 on file: '//TRIM(bseig_fname))
1305    do it=1,nstates
1306      write(eig_unt) ovlp(:,it)
1307    end do
1308 
1309    ABI_FREE(ovlp)
1310    close(eig_unt)
1311 
1312  CASE (.TRUE.)
1313 
1314 #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
1315    !
1316    ! Init scaLAPACK matrix Hbar = ( R   C )
1317    !                              ( C*  R*)
1318    ! Battle plan:
1319    !   Here the reading is complicated by the fact that R and C are stored on two different files
1320    !   and moreover the matrices are in packed storage mode.
1321    !   For initializing the local part of the resonant and anti-resonant block we have to allocate
1322    !   a temporary buffer. Then we read the buffer from file and the corresponding elements of the
1323    !   scaLAPACK matrix are initialized taking into account the symmetries of R (Hermitian)
1324    !   The same procedure is used to read the coupling and the anti-coupling part (Symmetric).
1325    !
1326    tbloc=50
1327    write(msg,'(2(a,i0))')". Using MPI-IO + scaLAPACK version with nprocs= ",nprocs,"; block size= ",tbloc
1328    call wrtout([std_out, ab_out], msg, do_flush=.True.)
1329    !
1330    ! Init scaLAPACK environment.
1331    call Slk_processor%init(comm)
1332    !
1333    ! Open the Resonant file with MPI-IO and skip the record.
1334    amode=MPI_MODE_RDONLY
1335 
1336    call MPI_FILE_OPEN(comm, reso_fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
1337    msg = " MPI_IO error opening file: "//TRIM(reso_fname)
1338    ABI_CHECK_MPI(mpi_err,msg)
1339    !
1340    ! Skip the header and find the offset for reading the matrix.
1341    call exc_skip_bshdr_mpio(mpi_fh,xmpio_collective,ehdr_offset)
1342    !
1343    ! Read  = ( R  - )
1344    !         ( -  R*)
1345    call Slk_Hbar%init(exc_size,exc_size,Slk_processor,istwfk1)
1346 
1347    nullify(myel2loc)
1348    nsblocks=nsppol
1349    ABI_MALLOC(sub_block,(2,2,nsblocks))
1350    ABI_CHECK(nsppol==1,"nsppol==2 not coded yet")
1351 
1352    call slk_single_fview_read_mask(Slk_Hbar,rrs_of_glob,offset_in_file,nsblocks,sub_block,my_nel,myel2loc,etype,slk_mask_type,&
1353 &    offset_err,is_fortran_file)
1354 
1355    if (offset_err/=0) then
1356      write(msg,"(3a)")&
1357 &      " Global position index cannot be stored in a standard Fortran integer ",ch10,&
1358 &      " Excitonic matrix cannot be read with a single MPI-IO call."
1359      ABI_ERROR(msg)
1360    end if
1361 
1362    ! Shift the offset because the view starts at the fist matrix element!
1363    ! TODO should rationalize the treatment of the offset
1364    my_offset = ehdr_offset + xmpio_bsize_frm
1365    call MPI_FILE_SET_VIEW(mpi_fh, my_offset, etype, slk_mask_type, 'native', MPI_INFO_NULL, mpi_err)
1366    ABI_CHECK_MPI(mpi_err,"SET_VIEW")
1367 
1368    call MPI_TYPE_FREE(slk_mask_type,mpi_err)
1369    ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
1370    !
1371    ! Read my portion of the R,-R* sublocks and store the values in a temporary buffer.
1372    ABI_MALLOC_OR_DIE(tmp_cbuffer,(my_nel), ierr)
1373 
1374    call xmpi_barrier(comm)
1375 
1376    call MPI_FILE_READ_ALL(mpi_fh, tmp_cbuffer, my_nel, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
1377    ABI_CHECK_MPI(mpi_err,"READ_ALL")
1378    !
1379    ! Symmetrize my Resonant part.
1380    do el=1,my_nel
1381      iloc = myel2loc(1,el)
1382      jloc = myel2loc(2,el)
1383      call Slk_Hbar%loc2glob(iloc,jloc,iglob,jglob)
1384      ctmp = tmp_cbuffer(el)
1385      if (iglob==jglob.and..not.Bsp%have_complex_ene) ctmp = DBLE(ctmp) ! Force the diagonal to be real.
1386      rrs_kind = rrs_of_glob(iglob,jglob,Slk_Hbar%sizeb_global)
1387      if (rrs_kind==1.and.jglob<iglob) then ! Lower resonant
1388        ctmp = DCONJG(ctmp)
1389      else if (rrs_kind==-1.and.jglob>=iglob) then  ! Lower Anti-resonant (Diagonal is included).
1390        ctmp = DCONJG(ctmp)
1391      end if
1392      Slk_Hbar%buffer_cplx(iloc,jloc) = ctmp
1393    end do
1394 
1395    ABI_FREE(tmp_cbuffer)
1396    ABI_FREE(myel2loc)
1397 
1398    call MPI_FILE_CLOSE(mpi_fh, mpi_err)
1399    ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
1400    !
1401    ! Read  = ( -  C)
1402    !         (-C* -)
1403    !
1404    call MPI_FILE_OPEN(comm, coup_fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
1405    msg = " MPI_IO error opening file: "//TRIM(coup_fname)
1406    ABI_CHECK_MPI(mpi_err,msg)
1407    !
1408    ! Skip the header and find the offset for reading the matrix.
1409    call exc_skip_bshdr_mpio(mpi_fh,xmpio_collective,ehdr_offset)
1410 
1411    nullify(myel2loc)
1412    call slk_single_fview_read_mask(Slk_Hbar,ccs_of_glob,offset_in_file,nsblocks,sub_block,my_nel,myel2loc,etype,slk_mask_type,&
1413 &    offset_err,is_fortran_file)
1414 
1415    ABI_FREE(sub_block)
1416 
1417    if (offset_err/=0) then
1418      write(msg,"(3a)")&
1419 &      " Global position index cannot be stored in a standard Fortran integer ",ch10,&
1420 &      " Excitonic matrix cannot be read with a single MPI-IO call."
1421      ABI_ERROR(msg)
1422    end if
1423    !
1424    ! Shift the offset because the view starts at the fist matrix element!
1425    ! TODO should rationalize the treatment of the offset so that the client code
1426    ! will automatically receive my_offset.
1427    my_offset = ehdr_offset + xmpio_bsize_frm
1428    call MPI_FILE_SET_VIEW(mpi_fh, my_offset, etype, slk_mask_type, 'native', MPI_INFO_NULL, mpi_err)
1429    ABI_CHECK_MPI(mpi_err,"SET_VIEW")
1430 
1431    call MPI_TYPE_FREE(slk_mask_type,mpi_err)
1432    ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
1433    !
1434    ! Read my portion of the C-C* blocks and store the values in a temporary buffer.
1435    ABI_MALLOC_OR_DIE(tmp_cbuffer,(my_nel), ierr)
1436 
1437    call MPI_FILE_READ_ALL(mpi_fh, tmp_cbuffer, my_nel, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
1438    ABI_CHECK_MPI(mpi_err,"READ_ALL")
1439    !
1440    ! Symmetrize my coupling part.
1441    ! Coupling block is symmetric => No symmetrization of the lower triangle.
1442    do el=1,my_nel
1443      iloc = myel2loc(1,el)
1444      jloc = myel2loc(2,el)
1445      call Slk_Hbar%loc2glob(iloc, jloc, iglob, jglob)
1446      ccs_kind = ccs_of_glob(iglob,jglob,Slk_Hbar%sizeb_global)
1447      ctmp = tmp_cbuffer(el)
1448      if (ccs_kind==-1) ctmp = DCONJG(ctmp) ! Anti-coupling (Diagonal is included).
1449      Slk_Hbar%buffer_cplx(iloc,jloc) = ctmp
1450    end do
1451 
1452    ABI_FREE(tmp_cbuffer)
1453    ABI_FREE(myel2loc)
1454 
1455    !max_r=20; max_c=10
1456    !call print_arr(Slk_Hbar%buffer_cplx,max_r=max_r,max_c=max_c,unit=std_out)
1457 
1458 !#ifdef DEV_MG_DEBUG_THIS
1459 !   ABI_MALLOC(exc_ham,(exc_size,exc_size))
1460 !   read(666)exc_ham
1461 !
1462 !   write(std_out,*)"Error Hbar: ",MAXVAL(ABS(exc_ham-Slk_Hbar%buffer_cplx))
1463 !   ABI_FREE(exc_ham)
1464 !#endif
1465 
1466    call MPI_FILE_CLOSE(mpi_fh, mpi_err)
1467    ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
1468    !
1469    ! Init scaLAPACK matrix F
1470    call Slk_F%init(exc_size,exc_size,Slk_processor,istwfk1)
1471    !
1472    ! Global F = (1  0)
1473    !            (0 -1)
1474    do jloc=1,Slk_F%sizeb_local(2)
1475      do iloc=1,Slk_F%sizeb_local(1)
1476        call Slk_F%loc2glob(iloc, jloc, iglob, jglob)
1477        if (iglob==jglob) then
1478          if (iglob<=SUM(Bsp%nreh)) then
1479            Slk_F%buffer_cplx(iloc,jloc) =  cone
1480          else
1481            Slk_F%buffer_cplx(iloc,jloc) = -cone
1482          end if
1483        else
1484          Slk_F%buffer_cplx(iloc,jloc) =  czero
1485        end if
1486      end do
1487    end do
1488    !
1489    ! ===========================================================
1490    ! ==== Solve generalized EV problem H u = F Hbar u = e u ====
1491    ! ===========================================================
1492    call Slk_vec%init(exc_size,exc_size,Slk_processor,istwfk1)
1493    !
1494    itype=2; vl=1; vu=1; il=1; iu=nstates
1495    abstol=zero !ABSTOL = PDLAMCH(comm,'U')
1496 
1497 !#if 1
1498    if (do_full_diago) then
1499      call slk_F%pzhegvx(itype,"Vectors","All","Upper",Slk_Hbar,vl,vu,il,iu,abstol,Slk_vec,mene_found,exc_ene)
1500    else
1501      ABI_WARNING("Partial diago is still under testing")
1502      call slk_F%pzhegvx(itype,"Vectors","Index","Upper",Slk_Hbar,vl,vu,il,iu,abstol,Slk_vec,mene_found,exc_ene)
1503    end if
1504 !#else
1505 !   call xhegv(itype,"Vectors","Upper",exc_size,Slk_F%buffer_cplx,Slk_Hbar%buffer_cplx,exc_ene)
1506 !   Slk_vec%buffer_cplx = Slk_F%buffer_cplx
1507 !#endif
1508 
1509 !#ifdef DEV_MG_DEBUG_THIS
1510 !   if (PRODUCT(Slk_Hbar%sizeb_local) /= exc_size**2) then
1511 !     ABI_ERROR("Wrong size")
1512 !   end if
1513 !
1514 !   ABI_MALLOC(exc_ham,(exc_size,exc_size))
1515 !   read(888)exc_ham
1516 !
1517 !   write(std_out,*)"Error rvec: ",MAXVAL(ABS(exc_ham-Slk_vec%buffer_cplx))
1518 !   ABI_FREE(exc_ham)
1519 !
1520 !   ABI_MALLOC(test_ene,(exc_size))
1521 !   read(888)test_ene
1522 !   write(std_out,*)"Error ene: ",MAXVAL(ABS(exc_ene-test_ene))
1523 !   ABI_FREE(test_ene)
1524 !#endif
1525 
1526    call Slk_F%free()
1527    call Slk_Hbar%free()
1528 
1529    call wrtout(std_out,ch10//" Writing eigenvalues and eigenvectors on file: "//TRIM(bseig_fname))
1530    !
1531    ! Open the file with Fortran-IO to write the Header.
1532    if (my_rank==master) then
1533      if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
1534        ABI_ERROR(msg)
1535      end if
1536 
1537      write(eig_unt) exc_size,nstates
1538      write(eig_unt) CMPLX(exc_ene(1:nstates),kind=dpc)
1539      !do mi=1,exc_size
1540      !  write(eig_unt) CMPLX(exc_rvect(:,mi),kind=dpc)
1541      !end do
1542      close(eig_unt)
1543    end if
1544    !
1545    ! Open the file with MPI-IO and write the distributed eigevectors.
1546    call xmpi_barrier(comm)
1547    amode=MPI_MODE_RDWR
1548    call MPI_FILE_OPEN(comm, bseig_fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
1549    ABI_CHECK_MPI(mpi_err,"FILE_OPEN: "//TRIM(bseig_fname))
1550    !
1551    ! Skip the header and find the offset for writing the matrix.
1552    ehdr_offset=0
1553    !call hdr_mpio_skip(mpi_fh,fform,ehdr_offset)
1554 
1555    call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,mpi_err)
1556    write(std_out,*)" fmarker1 = ",fmarker
1557    call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,mpi_err)
1558    write(std_out,*)" fmarker2 = ",fmarker
1559 
1560    write(std_out,*)" Writing nstates ",nstates
1561    gsub(:,1) = (/1,1/)
1562    gsub(:,2) = (/exc_size,nstates/)
1563    call slk_write(Slk_vec,"All",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset,glob_subarray=gsub)
1564 
1565    call wrtout(std_out,' Calculating overlap matrix... ')
1566    if (.not.do_full_diago) then
1567      ABI_ERROR(" Init of Slk_ovlp is wrong")
1568    end if
1569 
1570    call Slk_ovlp%init(exc_size,exc_size,Slk_processor,istwfk1)
1571 
1572    ! Calculate the overlap matrix.
1573    ! FIXME
1574    ! The ESLL manual says that "matrices matrix1 and matrix2 must have no common elements;
1575    ! otherwise, results are unpredictable."
1576    ! However the official scaLAPACK documentation does not report this (severe) limitation.
1577 
1578    !call Slk_tmp%init(exc_size,exc_size,Slk_processor,istwfk1)
1579    !Slk_tmp%buffer_cplx = Slk_vec%buffer_cplx
1580    !call slk_pgemm("C","N",Slk_tmp,cone,Slk_vec,czero,Slk_ovlp)
1581    !call Slk_tmp%free()
1582 
1583    call slk_pgemm("C","N",Slk_vec,cone,Slk_vec,czero,Slk_ovlp)
1584 
1585 !#ifdef DEV_MG_DEBUG_THIS
1586 !   ABI_MALLOC(exc_ham,(exc_size,exc_size))
1587 !   read(667)exc_ham
1588 !
1589 !   write(std_out,*)"Error Ovlp: ",MAXVAL(ABS(exc_ham-Slk_ovlp%buffer_cplx))
1590 !   !Slk_ovlp%buffer_cplx = exc_ham
1591 !#endif
1592 
1593    !max_r=20; max_c=10
1594    !call print_arr(Slk_ovlp%buffer_cplx,max_r=max_r,max_c=max_c,unit=std_out)
1595 
1596    call Slk_vec%free()
1597 
1598    call wrtout(std_out," Inverting overlap matrix... ")
1599    uplo="Upper"
1600 
1601 !#if 0
1602 !!DEBUG
1603 !   call xhdp_invert(uplo,Slk_ovlp%buffer_cplx,exc_size)
1604 !
1605 !   !call slk_symmetrize(Slk_ovlp,uplo,"Hermitian")
1606 !   call hermitianize(Slk_ovlp%buffer_cplx,uplo)
1607 !
1608 !   exc_ham = MATMUL(exc_ham,Slk_ovlp%buffer_cplx)
1609 !   do it=1,exc_size
1610 !     exc_ham(it,it) = exc_ham(it,it) - cone
1611 !   end do
1612 !
1613 !   write(std_out,*)"Error Inversion: ",MAXVAL(ABS(exc_ham))
1614 !   ABI_FREE(exc_ham)
1615 !!END DEBUG
1616 !
1617 !#else
1618    ! call Slk_ovlp%hpd_invert(uplo)
1619    ! call hermitianize(Slk_ovlp%buffer_cplx,uplo)
1620    ! !call slk_symmetrize(Slk_ovlp,uplo,"Hermitian")
1621 
1622    call Slk_ovlp%invert()  ! Version for generic complex matrix.
1623 !#endif
1624 
1625 !#ifdef DEV_MG_DEBUG_THIS
1626 !   ABI_MALLOC(exc_ham,(exc_size,exc_size))
1627 !   read(668)exc_ham
1628 !   write(std_out,*)"Error in Inv Ovlp: ",MAXVAL(ABS(exc_ham-Slk_ovlp%buffer_cplx))
1629 !
1630 !   !exc_ham = exc_ham-Slk_ovlp%buffer_cplx
1631 !   !do it=1,exc_size
1632 !   !  if ( MAXVAL(ABS(exc_ham(:,it))) > 0.1 ) write(std_out,*)"it: ",it,exc_ham(:,it)
1633 !   !end do
1634 !
1635 !   !Slk_ovlp%buffer_cplx = exc_ham
1636 !   ABI_FREE(exc_ham)
1637 !
1638 !   !write(std_out,*)"MAX ERR",MAXVAL(ABS(Slk_ovlp%buffer_cplx - TRANSPOSE(DCONJG(Slk_ovlp%buffer_cplx))))
1639 !#endif
1640 
1641    call wrtout(std_out,' Writing overlap matrix S^-1 on file: '//TRIM(bseig_fname))
1642 
1643    call slk_write(Slk_ovlp,"All",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset)
1644 
1645    call MPI_FILE_CLOSE(mpi_fh, mpi_err)
1646    ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
1647 
1648    call Slk_ovlp%free()
1649    call Slk_processor%free()
1650 #else
1651    ABI_BUG("You should not be here!")
1652 #endif
1653 
1654  END SELECT
1655 
1656  exc_gap    = MINVAL(ABS(exc_ene(1:nstates)))
1657  exc_maxene = MAXVAL(ABS(exc_ene(1:nstates)))
1658 
1659  write(msg,'(2(a,f7.2,2a))')&
1660   " First excitonic eigenvalue: ",exc_gap*Ha_eV,   " [eV].",ch10,&
1661   " Last  excitonic eigenvalue: ",exc_maxene*Ha_eV," [eV].",ch10
1662  call wrtout([std_out, ab_out], msg)
1663 
1664  nene_printed = MIN(32*nsppol,nstates); if (prtvol>10) nene_printed = nstates
1665  write(msg,'(a,i0)')' Complex excitonic eigenvalues in eV up to n= ',nene_printed
1666  call wrtout(std_out, msg)
1667 
1668  do it=0,(nene_printed-1)/4
1669    write(msg,'(4f10.5)') ( exc_ene(ii)*Ha_eV, ii=1+it*4,MIN(it*4+4,nene_printed) )
1670    call wrtout(std_out, msg)
1671  end do
1672 
1673  ABI_FREE(exc_ene)
1674 
1675 10 call xmpi_barrier(comm)
1676 
1677 end subroutine exc_diago_coupling_hegv

m_exc_diago/exc_diago_driver [ Functions ]

[ Top ] [ m_exc_diago ] [ Functions ]

NAME

  exc_diago_driver

FUNCTION

  Driver routine for the direct diagonalization of the Hermitian excitonic Hamiltonian.

INPUTS

  neh=Rank of the resonant block of the Hamiltonian.
  BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.
    %exh=Name of the file storing the excitonic resonant part.

OUTPUT

  Eigenvalues and eigenvectors are written on file.

SOURCE

 87 subroutine exc_diago_driver(Wfd,Bsp,BS_files,KS_BSt,QP_BSt,Cryst,Kmesh,Psps,&
 88 &  Pawtab,Hur,Hdr_bse,drude_plsmf,Epren)
 89 
 90 !Arguments ------------------------------------
 91 !scalars
 92  real(dp),intent(in) :: drude_plsmf
 93  type(excparam),intent(in) :: BSp
 94  type(excfiles),intent(in) ::  BS_files
 95  type(Hdr_type),intent(in) :: Hdr_bse
 96  type(crystal_t),intent(in) :: Cryst
 97  type(pseudopotential_type),intent(in) :: Psps
 98  type(kmesh_t),intent(in) :: Kmesh
 99  type(ebands_t),intent(in) :: KS_BSt,QP_BSt
100  type(wfdgw_t),intent(inout) :: Wfd
101  type(eprenorms_t),intent(in) :: Epren
102 !arrays
103  type(pawtab_type),intent(in) :: Pawtab(Cryst%ntypat*Wfd%usepaw)
104  type(pawhur_t),intent(in) :: Hur(Cryst%natom*Wfd%usepaw)
105 
106 !Local variables ------------------------------
107 !scalars
108  integer :: my_rank,master,comm,prtvol
109  complex(dpc) :: exc_gap,gw_gap
110  logical :: eval_eigenstates
111  character(len=500) :: msg
112 !arrays
113  real(dp) :: gaps(3,QP_BSt%nsppol)
114 
115 !************************************************************************
116 
117  DBG_ENTER("COLL")
118 
119  comm    = Wfd%comm
120  my_rank = Wfd%my_rank
121  master  = Wfd%master
122  prtvol  = Wfd%prtvol
123 
124  if (BSp%have_complex_ene) then
125    ABI_ERROR("Complex energies are not supported yet")
126  end if
127  !
128  ! This trick is needed to restart a CG run, use DDIAGO to calculate the spectra reusing an old BSEIG file.
129  eval_eigenstates = (BS_files%in_eig == BSE_NOFILE) .or. (Bsp%algorithm == BSE_ALGO_CG)
130 
131  if (eval_eigenstates) then
132    !
133    select case (BSp%algorithm)
134    case (BSE_ALGO_DDIAGO)
135      if (BSp%use_coupling==0) then
136        call exc_diago_resonant(BSp,BS_files,Hdr_bse,prtvol,comm)
137        if(Bsp%do_ep_renorm) then
138          call exc_diago_resonant(BSp,BS_files,Hdr_bse,prtvol,comm,Epren=Epren,Kmesh=Kmesh,Cryst=Cryst,elph_lifetime=.TRUE.)
139        end if
140      else
141        if (Bsp%have_complex_ene) then
142          ! Solve Hv = ev with generic complex matrix.
143          call exc_diago_coupling(BSp,BS_files,Hdr_bse,prtvol,comm)
144        else
145          ! Solve generalized eigenvalue problem F Hbar with Hbar Hermitian definitive positive matrix.
146          call exc_diago_coupling_hegv(BSp,BS_files,Hdr_bse,prtvol,comm)
147        end if
148      end if
149 
150    case (BSE_ALGO_CG)
151      if (BSp%use_coupling==0) then
152        call exc_iterative_diago(Bsp,BS_files,Hdr_bse,prtvol,comm)
153      else
154        ABI_ERROR("CG + coupling not coded")
155      end if
156 
157    case default
158      write(msg,'(a,i0)')" Wrong value for Bsp%algorithm: ",Bsp%algorithm
159      ABI_ERROR(msg)
160    end select
161    !
162    if (my_rank==master) then
163      call ebands_report_gap(QP_BSt,header="QP bands",unit=std_out,gaps=gaps)
164      gw_gap = MINVAL(gaps(2,:))
165      call exc_print_eig(BSp,BS_files%out_eig,gw_gap,exc_gap)
166    end if
167    call xmpi_barrier(comm)
168    !
169  end if
170 
171  call build_spectra(BSp,BS_files,Cryst,Kmesh,KS_BSt,QP_BSt,Psps,Pawtab,Wfd,Hur,drude_plsmf,comm)
172 
173  ! Electron-phonon renormalization !
174  if (BSp%algorithm == BSE_ALGO_DDIAGO .and. BSp%use_coupling == 0 .and. BSp%do_ep_renorm) then
175    call build_spectra(BSp,BS_files,Cryst,Kmesh,KS_BSt,QP_BSt,Psps,Pawtab,Wfd,Hur,drude_plsmf,comm,Epren=Epren)
176  end if
177 
178  DBG_EXIT("COLL")
179 
180 end subroutine exc_diago_driver

m_exc_diago/exc_diago_resonant [ Functions ]

[ Top ] [ m_exc_diago ] [ Functions ]

NAME

  exc_diago_resonant

FUNCTION

  Calculates eigenvalues and eigenvectors of the Hermitian excitonic Hamiltonian (coupling is neglected).

INPUTS

  Bsp
  BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.
  comm=MPI communicator.
  bseig_fname=The name of the output file
  prtvol=Verbosity level.

OUTPUT

  Eigenvalues and eigenvectors are written on file bseig_fname

SOURCE

204 subroutine exc_diago_resonant(Bsp,BS_files,Hdr_bse,prtvol,comm,Epren,Kmesh,Cryst,elph_lifetime)
205 
206 !Arguments ------------------------------------
207 !scalars
208  integer,intent(in) :: comm,prtvol
209  logical,optional,intent(in) :: elph_lifetime
210  type(excparam),intent(in) :: BSp
211  type(excfiles),intent(in) :: BS_files
212  type(Hdr_type),intent(in) :: Hdr_bse
213  type(eprenorms_t),optional,intent(in) :: Epren
214  type(kmesh_t),optional,intent(in) :: Kmesh
215  type(crystal_t),optional,intent(in) :: Cryst
216 
217 !Local variables ------------------------------
218 !scalars
219  integer,parameter :: master=0
220  integer :: ii,it,mi,hreso_unt,eig_unt,exc_size,neh1,neh2,j
221  integer :: nsppol,il,iu,mene_found,nstates
222  integer :: nprocs,my_rank,fform,nene_printed,ierr
223  real(dp) :: exc_gap,exc_maxene,abstol
224  real(dp) :: vl,vu
225  logical :: use_scalapack,do_full_diago,diagonal_is_real
226  character(len=500) :: msg
227  character(len=fnlen) :: hreso_fname,bseig_fname
228 !arrays
229  real(dp),allocatable :: exc_ene(:)
230  complex(dpc),allocatable :: exc_mat(:,:),exc_vec(:,:)
231 #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
232  integer :: amode,mpi_fh,istwf_k,tbloc
233  integer(XMPI_OFFSET_KIND) :: ehdr_offset,fmarker
234  integer :: block_sizes(2,3),array_of_sizes(2),gsub(2,2)
235  logical,parameter :: is_fortran_file=.TRUE.
236  real(dp),external :: PDLAMCH
237  type(matrix_scalapack)    :: Slk_mat,Slk_vec
238  type(processor_scalapack) :: Slk_processor
239 #endif
240 
241  integer :: ik, ic, iv, isppol, ireh, ep_ik, itemp
242  complex(dpc) :: en
243 
244  real(dp) :: dksqmax
245  integer,allocatable :: bs2eph(:,:)
246  integer :: sppoldbl, timrev
247  logical :: do_ep_renorm, do_ep_lifetime
248  integer :: ntemp
249  character(len=4) :: ts
250  complex(dpc),allocatable :: exc_vl(:,:),exc_ene_c(:)
251  complex(dpc) :: ctemp
252 !! complex(dpc),allocatable :: ovlp(:,:)
253 
254 !************************************************************************
255 
256  DBG_ENTER("PERS")
257 
258  nprocs  = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
259 
260  if (BSp%have_complex_ene) then ! QP lifetimes are not included
261    ABI_ERROR("complex energies not coded yet")
262  end if
263 
264  if (ANY(Bsp%nreh/=Bsp%nreh(1))) then
265    write(std_out,*)" Bsp%nreh: ",Bsp%nreh
266    write(msg,'(a)')" BSE code does not support different number of transitions for the two spin channels"
267    ABI_WARNING(msg)
268  end if
269 
270  nsppol   = Hdr_bse%nsppol
271  exc_size = SUM(BSp%nreh)
272  nstates  = BSp%nstates; do_full_diago=(Bsp%nstates==exc_size)
273 
274  neh1 = Bsp%nreh(1); neh2 = neh1
275  if (Hdr_bse%nsppol==2) neh2 = Bsp%nreh(2)
276 
277  ! Scalapack is disabled due to portability issues in slk_read
278  ! This part should be rewritten  with hdf5 + mpi-io
279 
280  use_scalapack = .FALSE.
281 !#if defined HAVE_LINALG_SCALAPACK
282 ! use_scalapack = (nprocs > 1)
283 !#endif
284  if (use_scalapack .and. nsppol == 2) then
285    use_scalapack = .False.
286    msg = "Scalapack with nsppol==2 not yet available. Using sequential version"
287    ABI_WARNING(msg)
288  end if
289 
290  if (.not.use_scalapack .and. my_rank/=master) GOTO 10 ! Inversion is done by master only.
291 
292  nene_printed = MIN(32*nsppol,nstates); if (prtvol>10) nene_printed = nstates
293 
294  if (BS_files%in_hreso /= BSE_NOFILE) then
295    hreso_fname = BS_files%in_hreso
296  else
297    hreso_fname = BS_files%out_hreso
298  end if
299 
300  bseig_fname = BS_files%out_eig
301  if (BS_files%in_eig /= BSE_NOFILE) then
302    ABI_ERROR("BS_files%in_eig is defined!")
303  end if
304 
305  write(msg,'(a,i0)')' Direct diagonalization of the resonant excitonic Hamiltonian, Matrix size= ',exc_size
306  call wrtout([std_out, ab_out], msg)
307 
308  ABI_MALLOC_OR_DIE(exc_ene,(exc_size), ierr)
309 
310  ABI_MALLOC_OR_DIE(exc_ene_c,(exc_size), ierr)
311 
312  do_ep_renorm = .FALSE.
313  ntemp = 1
314  do_ep_lifetime = .FALSE.
315  if(BSp%do_ep_renorm .and. present(Epren)) then
316    do_ep_renorm = .TRUE.
317    ntemp = Epren%ntemp
318    if(present(elph_lifetime)) then
319      do_ep_lifetime = elph_lifetime
320    end if
321  end if
322 
323  if (do_ep_renorm) then
324    ABI_CHECK(nsppol == 1, "Nsppol == 2 not supported with elphon renormalizations")
325  end if
326 
327  SELECT CASE (use_scalapack)
328  CASE (.FALSE.)
329 
330    write(msg,'(a)')". Using LAPACK sequential version. "
331    call wrtout([std_out, ab_out], msg)
332    write(msg,'(a,f8.1,a)')' Allocating excitonic eigenvalues. Memory required: ', exc_size*dp*b2Mb,' Mb. '
333    call wrtout(std_out, msg)
334 
335    write(msg,'(a,f8.1,a)')' Allocating excitonic hamiltonian.  Memory required: ',exc_size**2*dpc*b2Mb,' Mb.'
336    call wrtout(std_out, msg, do_flush=.True.)
337 
338    ABI_MALLOC_OR_DIE(exc_mat,(exc_size,exc_size), ierr)
339 
340    if (do_ep_renorm) then
341      ABI_MALLOC_OR_DIE(exc_vl,(exc_size,exc_size),ierr)
342    end if
343    !exc_mat = HUGE(zero)
344    !
345    ! Read data from file.
346    if (open_file(hreso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
347      ABI_ERROR(msg)
348    end if
349    !
350    ! Read the header and perform consistency checks.
351    call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
352    ABI_CHECK(ierr==0,"Fatal error, cannot continue")
353    !
354    ! Construct full resonant block using Hermiticity.
355    diagonal_is_real = .not.Bsp%have_complex_ene
356    call exc_read_rblock_fio(hreso_unt,diagonal_is_real,nsppol,Bsp%nreh,exc_size,exc_mat,ierr)
357    ABI_CHECK(ierr==0,"Fatal error, cannot continue")
358 
359    close(hreso_unt)
360 
361    if (do_ep_renorm) then
362      write(std_out,'(a)') "Mapping kpts from bse to eph"
363      sppoldbl = 1 !; if (any(Cryst%symafm == -1) .and. Epren%nsppol == 1) nsppoldbl=2
364      ABI_MALLOC(bs2eph, (Kmesh%nbz*sppoldbl, 6))
365      timrev = 1
366      call listkk(dksqmax, Cryst%gmet, bs2eph, Epren%kpts, Kmesh%bz, Epren%nkpt, Kmesh%nbz, Cryst%nsym, &
367         sppoldbl, Cryst%symafm, Cryst%symrel, timrev, xmpi_comm_self, use_symrec=.False.)
368    end if
369 
370    do itemp = 1, ntemp
371 
372      !TODO should find a way not to read again and again !
373      !  but without storing it twice !!!
374      !exc_mat = HUGE(zero)
375      !
376      ! Read data from file.
377      if (open_file(hreso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
378        ABI_ERROR(msg)
379      end if
380      !
381      ! Read the header and perform consistency checks.
382      call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
383      ABI_CHECK(ierr==0,"Fatal error, cannot continue")
384      !
385      ! Construct full resonant block using Hermiticity.
386      diagonal_is_real = .not.Bsp%have_complex_ene
387      call exc_read_rblock_fio(hreso_unt,diagonal_is_real,nsppol,Bsp%nreh,exc_size,exc_mat,ierr)
388      ABI_CHECK(ierr==0,"Fatal error, cannot continue")
389 
390      close(hreso_unt)
391 
392      bseig_fname = BS_files%out_eig
393 
394      if (do_ep_renorm) then
395        write(std_out,'(a,i4)') "Will perform elphon renormalization for itemp = ",itemp
396 
397        call int2char4(itemp,ts)
398 
399        bseig_fname = TRIM(BS_files%out_eig) // TRIM("_T") // ts
400 
401        ! Should patch the diagonal of exc_mat
402 
403        do isppol = 1, BSp%nsppol
404          do ireh = 1, BSp%nreh(isppol)
405            ic = BSp%Trans(ireh,isppol)%c
406            iv = BSp%Trans(ireh,isppol)%v
407            ik = BSp%Trans(ireh,isppol)%k ! In the full bz
408            en = BSp%Trans(ireh,isppol)%en
409 
410            ep_ik = bs2eph(ik,1)
411 
412            !TODO support multiple spins !
413            if(ABS(en - (Epren%eigens(ic,ep_ik,isppol)-Epren%eigens(iv,ep_ik,isppol)+BSp%mbpt_sciss)) > tol3) then
414              ABI_ERROR("Eigen from the transition does not correspond to the EP file !")
415            end if
416            exc_mat(ireh,ireh) = exc_mat(ireh,ireh) + (Epren%renorms(1,ic,ik,isppol,itemp) - Epren%renorms(1,iv,ik,isppol,itemp))
417 
418            ! Add lifetime
419            if(do_ep_lifetime) then
420              exc_mat(ireh,ireh) = exc_mat(ireh,ireh) - j_dpc*(Epren%linewidth(1,ic,ik,isppol,itemp) &
421 &                + Epren%linewidth(1,iv,ik,isppol,itemp))
422            end if
423 
424          end do
425        end do
426 
427      end if
428 
429      if (do_full_diago) then
430        if(do_ep_renorm) then
431          call wrtout(std_out," Full diagonalization with XGEEV... ")
432          ABI_MALLOC(exc_vec,(exc_size,exc_size))
433          call xgeev('V','V',exc_size,exc_mat,exc_size,exc_ene_c,exc_vl,exc_size,exc_vec,exc_size)
434          exc_mat(:,1:nstates) = exc_vec
435          ABI_FREE(exc_vec)
436        else
437          call wrtout(std_out," Full diagonalization with XHEEV... ")
438          call xheev("Vectors","Upper",exc_size,exc_mat,exc_ene)
439          exc_ene_c(:) = exc_ene(:)
440        end if
441      else
442        call wrtout(std_out," Partial diagonalization with XHEEVX... ")
443        abstol=zero; il=1; iu=nstates
444        ABI_MALLOC_OR_DIE(exc_vec,(exc_size,nstates),ierr)
445        call xheevx("Vectors","Index","Upper",exc_size,exc_mat,vl,vu,il,iu,abstol,mene_found,exc_ene,exc_vec,exc_size)
446        exc_mat(:,1:nstates) = exc_vec
447        exc_ene_c(:) = exc_ene(:)
448        ABI_FREE(exc_vec)
449      end if
450      !
451      ! ==============================================
452      ! === Now exc_mat contains the eigenvectors ====
453      ! ==============================================
454 
455      ! * Write the final results.
456      call wrtout(std_out,' Writing eigenvalues and eigenvectors to file: '//TRIM(bseig_fname))
457 
458      if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
459        ABI_ERROR(msg)
460      end if
461 
462      !!! !DBYG
463      !!! !Compute overlap matrix
464      !!! ABI_MALLOC(ovlp,(exc_size,exc_size))
465      !!! do mi=1,nstates
466      !!!   do ireh=1,nstates
467      !!!     ovlp(mi,ireh) = xdotc(exc_size,exc_vl(:,mi),1,exc_mat(:,ireh),1)
468      !!!     if(mi==ireh) then
469      !!!       !if(ABS(ovlp(mi,ireh)) < 0.999) then
470      !!!       !  write(*,*) "it,itp = ",mi,ireh,"ovlp = ",ovlp(mi,ireh)
471      !!!       !end if
472      !!!     else
473      !!!       if(ABS(ovlp(mi,ireh)) > 0.001) then
474      !!!         write(*,*) "it,itp = ",mi,ireh,"ovlp = ",ovlp(mi,ireh)
475      !!!       end if
476      !!!     end if
477      !!!   end do
478      !!! end do
479      !!! !call xgemm("C","N",exc_size,nstates,nstates,cone,exc_vl,exc_size,exc_mat,exc_size,czero,ovlp,nstates)
480 
481      !!! write(777,*) ovlp
482      !!! ABI_FREE(ovlp)
483      !!! !ENDDBYG
484 
485      !% fform = 1002 ! FIXME
486      !% call hdr_io_int(fform,Hdr_bse,2,eig_unt)
487 
488      write(eig_unt) do_ep_lifetime
489      write(eig_unt) exc_size, nstates
490      write(eig_unt) exc_ene_c(1:nstates)
491      do mi=1,nstates
492        write(eig_unt) exc_mat(1:exc_size,mi)
493        if(do_ep_lifetime) then
494          write(eig_unt) exc_vl(1:exc_size,mi)
495        end if
496      end do
497 
498      close(eig_unt)
499 
500    end do ! itemp
501 
502    ABI_FREE(exc_mat)
503    if (do_ep_renorm) then
504      ABI_FREE(exc_vl)
505      ABI_FREE(bs2eph)
506    end if
507 
508  CASE (.TRUE.)
509 
510 #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
511    if (nsppol==2) then
512      ABI_WARNING("nsppol==2 + scalapack not coded yet")
513    end if
514 
515    istwf_k=1; tbloc=50
516    write(msg,'(2(a,i0))')". Using scaLAPACK version with nprocs= ",nprocs,"; block size= ",tbloc
517    call wrtout([std_out, ab_out], msg)
518 
519    write(msg,'(a,f8.1,a)')' Allocating excitonic eigenvalues. Memory required: ',exc_size*dp*b2Mb,' Mb. '
520    call wrtout(std_out, msg)
521    !
522    ! Init scaLAPACK environment.
523    call Slk_processor%init(comm)
524    !
525    ! Init scaLAPACK matrices
526    call Slk_mat%init(exc_size,exc_size,Slk_processor,istwf_k)
527    call Slk_vec%init(exc_size,exc_size,Slk_processor,istwf_k)
528    !
529    ! Open the file with MPI-IO and skip the record.
530    amode=MPI_MODE_RDONLY
531 
532    call MPI_FILE_OPEN(comm, hreso_fname, amode, MPI_INFO_NULL, mpi_fh, ierr)
533    ABI_CHECK_MPI(ierr,"MPI_IO error opening file: "//TRIM(hreso_fname))
534 
535    ! Skip the header and find the offset for reading the matrix.
536    call exc_skip_bshdr_mpio(mpi_fh,xmpio_collective,ehdr_offset)
537    !
538    ! Read scaLAPACK matrix from the file.
539    if (nsppol==1) then
540      call slk_read(Slk_mat,"Upper","Hermitian",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset)
541    else
542      array_of_sizes = (/exc_size,exc_size/)
543      block_sizes(:,1) = (/neh1,neh1/)
544      block_sizes(:,2) = (/neh2,neh2/)
545      block_sizes(:,3) = (/neh1,neh2/)
546      ABI_ERROR("Not tested")
547      !call slk_read_from_blocks(Slk_mat,array_of_sizes,block_sizes,is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset)
548    end if
549 
550    call MPI_FILE_CLOSE(mpi_fh, ierr)
551    ABI_CHECK_MPI(ierr,"FILE_CLOSE")
552 
553    if (do_full_diago) then
554      call wrtout(std_out," Performing full diagonalization with scaLAPACK...")
555      call slk_mat%heev("Vectors","Upper",Slk_vec,exc_ene)
556    else
557      call wrtout(std_out," Performing partial diagonalization with scaLAPACK...")
558      il=1; iu=nstates; abstol=zero !ABSTOL = PDLAMCH(comm,'U')
559      call slk_mat%pzheevx("Vectors","Index","Upper",vl,vu,il,iu,abstol,Slk_vec,mene_found,exc_ene)
560    end if
561 
562    exc_ene_c(:) = exc_ene(:)
563 
564    call Slk_mat%free()
565 
566    call wrtout(std_out,' Writing eigenvalues/vectors to file: '//TRIM(bseig_fname), do_flush=.True.)
567 
568    ! Write distributed matrix on file bseig_fname with Fortran records.
569    if (my_rank==master) then ! Write exc eigenvalues. Vectors will be appended in slk_write.
570      if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
571        ABI_ERROR(msg)
572      end if
573      write(eig_unt) exc_size, nstates
574      write(eig_unt) exc_ene_c(1:nstates)
575      close(eig_unt)
576    end if
577 
578    call xmpi_barrier(comm)
579    !
580    ! Open the file with MPI-IO and skip the record.
581    amode=MPI_MODE_RDWR
582 
583    call MPI_FILE_OPEN(comm, bseig_fname, amode, MPI_INFO_NULL, mpi_fh, ierr)
584    ABI_CHECK_MPI(ierr,"MPI_IO error opening file: "//TRIM(hreso_fname))
585 
586    !call MPI_FILE_SYNC(mpi_fh,ierr)
587 
588    ehdr_offset = 0
589    call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,ierr)
590    call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,ierr)
591 
592    write(std_out,*)"Writing nstates ",nstates
593    gsub(:,1) = (/1,1/)
594    gsub(:,2) = (/exc_size,nstates/)
595    call slk_write(Slk_vec,"All",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset,glob_subarray=gsub)
596 
597    call MPI_FILE_CLOSE(mpi_fh, ierr)
598    ABI_CHECK_MPI(ierr,"FILE_CLOSE")
599 
600    call Slk_vec%free()
601    call Slk_processor%free()
602    call xmpi_barrier(comm)
603 #else
604    ABI_BUG("You should not be here!")
605 #endif
606 
607  END SELECT
608 
609  ! Order the eigenvalues
610  do ii=nstates,2,-1
611    do j=1,ii-1
612      if (DBLE(exc_ene_c(j)) > DBLE(exc_ene_c(j+1))) then
613        ctemp = exc_ene_c(j)
614        exc_ene_c(j) = exc_ene_c(j+1)
615        exc_ene_c(j+1) = ctemp
616      end if
617    end do
618  end do
619 
620 
621  write(msg,'(a,i4)')' Excitonic eigenvalues in eV up to n= ',nene_printed
622  call wrtout([std_out, ab_out], msg)
623 
624  do it=0,(nene_printed-1)/8
625    write(msg,'(8f10.5)') ( DBLE(exc_ene_c(ii))*Ha_eV, ii=1+it*8,MIN(it*8+8,nene_printed) )
626    call wrtout([std_out, ab_out], msg)
627  end do
628 
629  exc_gap    = MINVAL(DBLE(exc_ene_c(1:nstates)))
630  exc_maxene = MAXVAL(DBLE(exc_ene_c(1:nstates)))
631 
632  write(msg,'(a,2(a,f7.2,2a),a)')ch10,&
633   " First excitonic eigenvalue= ",exc_gap*Ha_eV,   " [eV]",ch10,&
634   " Last  excitonic eigenvalue= ",exc_maxene*Ha_eV," [eV]",ch10,ch10
635  call wrtout([std_out, ab_out], msg, do_flush=.True.)
636 
637  ABI_FREE(exc_ene_c)
638  ABI_FREE(exc_ene)
639 
640 10 call xmpi_barrier(comm)
641 
642  DBG_EXIT("PERS")
643 
644 end subroutine exc_diago_resonant

m_exc_diago/exc_print_eig [ Functions ]

[ Top ] [ m_exc_diago ] [ Functions ]

NAME

  exc_print_eig

FUNCTION

  Print excitonic eigenvalues on std_out and ab_out.

INPUTS

  gw_gap=GW direct gap.
  bseig_fname=The name of file containing eigenvalues and eigenvectors

OUTPUT

  exc_gap=Excitonic direct gap.
  Additional info on the Excitonic spectrum are reported on standard output.

SOURCE

666 subroutine exc_print_eig(BSp,bseig_fname,gw_gap,exc_gap)
667 
668 !Arguments ------------------------------------
669 !scalars
670  complex(dpc),intent(in) :: gw_gap
671  complex(dpc),intent(out) :: exc_gap
672  character(len=*),intent(in) :: bseig_fname
673  type(excparam),intent(in) :: BSp
674 
675 !Local variables ------------------------------
676 !scalars
677  integer :: nstates_read,ii,j,k,eig_unt,ieig,hsize_exp
678  integer :: hsize_read !,nstates
679  complex(dpc) :: bind_energy,ctemp
680  character(len=500) :: msg
681  !type(Hdr_type) :: tmp_Hdr
682 !arrays
683  integer,allocatable :: iperm(:)
684  real(dp),allocatable :: exc_rene(:)
685  complex(dpc),allocatable :: exc_cene(:)
686 
687 !************************************************************************
688 
689  exc_gap = czero
690 
691  if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",status="old",action="read") /= 0) then
692    ABI_ERROR(msg)
693  end if
694 
695  read(eig_unt) ! do_ep_lifetime
696  read(eig_unt) hsize_read, nstates_read
697 
698  if (BSp%use_coupling==0) hsize_exp =   SUM(Bsp%nreh)
699  if (BSp%use_coupling>0)  hsize_exp = 2*SUM(Bsp%nreh)
700 
701  if (hsize_exp /= hsize_read) then
702    write(msg,'(2(a,i0))')" Wrong dimension: read: ",hsize_read," expected= ",hsize_exp
703    ABI_ERROR(msg)
704  end if
705 
706  ABI_MALLOC(exc_cene,(nstates_read))
707  read(eig_unt) exc_cene(:)
708 
709  ABI_MALLOC(exc_rene,(nstates_read))
710  exc_rene = DBLE(exc_cene)
711 
712  ABI_MALLOC(iperm,(nstates_read))
713  iperm = (/(ii, ii=1,nstates_read)/)
714 
715  call sort_dp(nstates_read,exc_rene,iperm,tol6)
716 
717  ABI_FREE(exc_rene)
718  ABI_FREE(iperm)
719 
720  ! put in ascending order
721  do ii=nstates_read,2,-1
722    do j=1,ii-1
723      if (DBLE(exc_cene(j)) > DBLE(exc_cene(j+1))) then
724        ctemp = exc_cene(j)
725        exc_cene(j) = exc_cene(j+1)
726        exc_cene(j+1) = ctemp
727      end if
728    end do
729  end do
730 
731  exc_gap = DCMPLX(ABS(DBLE(exc_cene(1))),AIMAG(exc_cene(1)))
732 
733  do ii=1,nstates_read
734    if (ABS(DBLE(exc_cene(ii))) < DBLE(exc_gap)) then
735      exc_gap = DCMPLX(ABS(DBLE(exc_cene(ii))),AIMAG(exc_cene(ii)))
736    end if
737  end do
738 
739  bind_energy = gw_gap - exc_gap
740 
741  write(msg,"(3(a,2f6.2,2a))")&
742 &  " GW  direct gap     ",gw_gap*Ha_eV,     " [eV] ",ch10,&
743 &  " EXC direct gap     ",exc_gap*Ha_eV,    " [eV] ",ch10,&
744 &  " EXC binding energy ",bind_energy*Ha_eV," [eV] ",ch10
745  call wrtout([std_out, ab_out], msg)
746 
747  msg=' Excitonic eigenvalues up to the GW energy gap [eV]'
748  call wrtout([std_out, ab_out], msg)
749 
750  do ii=1,nstates_read
751    if (DBLE(exc_cene(ii)) > zero) EXIT
752  end do
753 
754  do j=ii,nstates_read
755    if (DBLE(exc_cene(j)) > DBLE(gw_gap)) EXIT
756  end do
757  j=j-1
758 
759  do ieig=ii,j
760    write(msg,'(i3,a,2f6.2,a)')ieig," (",exc_cene(ieig)*Ha_eV,")"
761    call wrtout([std_out, ab_out], msg)
762  end do
763 
764  ii=ii-1
765  do j=ii,1,-1
766    if (ABS(DBLE(exc_cene(j))) > DBLE(gw_gap)) EXIT
767  end do
768  j=j+1
769 
770  ! This coding is not portable, write to ab_out has been disabled.
771  if (ii>0) then
772    do k=ii,j,-1
773      write(msg,'(i3,a,2f6.2,a)')k," (",exc_cene(k)*Ha_eV,")"
774      call wrtout(std_out, msg)
775    end do
776  end if
777 
778  ABI_FREE(exc_cene)
779 
780  close(eig_unt)
781 
782 end subroutine exc_print_eig