LCOV - code coverage report
Current view: top level - src/71_bse - m_exc_diago.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 69.0 % 449 310
Test Date: 2026-11-12 07:43:35 Functions: 80.0 % 5 4
Branches: 44.5 % 807 359

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_exc_diago
       2                 :             : !! NAME
       3                 :             : !! m_exc_diago
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!
       7                 :             : !! COPYRIGHT
       8                 :             : !! Copyright (C) 2009-2026 ABINIT and EXC groups (L.Reining, V.Olevano, F.Sottile, S.Albrecht, G.Onida, M.Giantomassi)
       9                 :             : !!  This file is distributed under the terms of the
      10                 :             : !!  GNU General Public License, see ~abinit/COPYING
      11                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      12                 :             : !!
      13                 :             : !! SOURCE
      14                 :             : 
      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_MPI
      28                 :             :  use m_xmpi
      29                 :             :  use m_hdr
      30                 :             :  use m_sort
      31                 :             :  use m_slk
      32                 :             : 
      33                 :             :  use defs_datatypes,    only : pseudopotential_type
      34                 :             :  use m_io_tools,        only : open_file
      35                 :             :  use m_fstrings,        only : int2char4
      36                 :             :  use m_numeric_tools,   only : print_arr, hermitianize
      37                 :             :  use m_crystal,         only : crystal_t
      38                 :             :  use m_kpts,            only : listkk
      39                 :             :  use m_bz_mesh,         only : kmesh_t
      40                 :             :  use m_ebands,          only : ebands_t
      41                 :             :  use m_eprenorms,       only : eprenorms_t
      42                 :             :  use m_wfd,             only : wfdgw_t
      43                 :             :  use m_paw_hr,          only : pawhur_t
      44                 :             :  use m_pawtab,          only : pawtab_type
      45                 :             :  use m_exc_itdiago,     only : exc_iterative_diago
      46                 :             :  use m_hide_lapack,     only : xheev, xheevx, xgeev, xhegvx, xginv, xhdp_invert, xhegv
      47                 :             :  use m_hide_blas,       only : xdotc, xgemm
      48                 :             :  use m_bse_io,          only : exc_fullh_from_blocks, offset_in_file, rrs_of_glob, ccs_of_glob, &
      49                 :             : &                              exc_read_bshdr, exc_skip_bshdr_mpio, exc_read_rblock_fio
      50                 :             :  use m_exc_spectra,     only : build_spectra
      51                 :             : 
      52                 :             :  implicit none
      53                 :             : 
      54                 :             :  private
      55                 :             : 
      56                 :             : #if defined HAVE_MPI1
      57                 :             :  include 'mpif.h'
      58                 :             : #endif
      59                 :             : 
      60                 :             : !#define DEV_MG_DEBUG_THIS
      61                 :             : 
      62                 :             :  public ::  exc_diago_driver ! Driver routine for the direct diagonalization of the BSE Hamiltonian (main entry point)
      63                 :             : !!***
      64                 :             : 
      65                 :             : contains
      66                 :             : 
      67                 :             : !!****f* m_exc_diago/exc_diago_driver
      68                 :             : !! NAME
      69                 :             : !!  exc_diago_driver
      70                 :             : !!
      71                 :             : !! FUNCTION
      72                 :             : !!  Driver routine for the direct diagonalization of the Hermitian excitonic Hamiltonian.
      73                 :             : !!
      74                 :             : !! INPUTS
      75                 :             : !!  neh=Rank of the resonant block of the Hamiltonian.
      76                 :             : !!  BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.
      77                 :             : !!    %exh=Name of the file storing the excitonic resonant part.
      78                 :             : !!
      79                 :             : !! OUTPUT
      80                 :             : !!  Eigenvalues and eigenvectors are written on file.
      81                 :             : !!
      82                 :             : !! SOURCE
      83                 :             : 
      84                 :           6 : subroutine exc_diago_driver(Wfd,Bsp,BS_files,KS_BSt,QP_BSt,Cryst,Kmesh,Psps,&
      85                 :           6 : &  Pawtab,Hur,Hdr_bse,drude_plsmf,Epren)
      86                 :             : 
      87                 :             : !Arguments ------------------------------------
      88                 :             : !scalars
      89                 :             :  real(dp),intent(in) :: drude_plsmf
      90                 :             :  type(excparam),intent(in) :: BSp
      91                 :             :  type(excfiles),intent(in) ::  BS_files
      92                 :             :  type(Hdr_type),intent(in) :: Hdr_bse
      93                 :             :  type(crystal_t),intent(in) :: Cryst
      94                 :             :  type(pseudopotential_type),intent(in) :: Psps
      95                 :             :  type(kmesh_t),intent(in) :: Kmesh
      96                 :             :  type(ebands_t),intent(in) :: KS_BSt,QP_BSt
      97                 :             :  type(wfdgw_t),intent(inout) :: Wfd
      98                 :             :  type(eprenorms_t),intent(in) :: Epren
      99                 :             : !arrays
     100                 :             :  type(pawtab_type),intent(in) :: Pawtab(Cryst%ntypat*Wfd%usepaw)
     101                 :             :  type(pawhur_t),intent(in) :: Hur(Cryst%natom*Wfd%usepaw)
     102                 :             : 
     103                 :             : !Local variables ------------------------------
     104                 :             : !scalars
     105                 :             :  integer :: my_rank,master,comm,prtvol
     106                 :             :  complex(dp) :: exc_gap,gw_gap
     107                 :             :  logical :: eval_eigenstates
     108                 :             :  character(len=500) :: msg
     109                 :             : !arrays
     110                 :          12 :  real(dp) :: gaps(3,QP_BSt%nsppol)
     111                 :             : !************************************************************************
     112                 :             : 
     113                 :             :  DBG_ENTER("COLL")
     114                 :             : 
     115                 :           6 :  comm    = Wfd%comm
     116                 :           6 :  my_rank = Wfd%my_rank
     117                 :           6 :  master  = Wfd%master
     118                 :           6 :  prtvol  = Wfd%prtvol
     119                 :             : 
     120         [ -  + ]:           6 :  if (BSp%have_complex_ene) then
     121                 :           0 :    ABI_ERROR("Complex energies are not supported yet")
     122                 :             :  end if
     123                 :             :  !
     124                 :             :  ! This trick is needed to restart a CG run, use DDIAGO to calculate the spectra reusing an old BSEIG file.
     125   [ -  +  -  - ]:           6 :  eval_eigenstates = (BS_files%in_eig == BSE_NOFILE) .or. (Bsp%algorithm == BSE_ALGO_CG)
     126                 :             : 
     127                 :             :  if (eval_eigenstates) then
     128                 :             :    !
     129                 :          11 :    select case (BSp%algorithm)
     130                 :             :    case (BSE_ALGO_DDIAGO)
     131         [ +  + ]:           5 :      if (BSp%use_coupling==0) then
     132                 :           4 :        call exc_diago_resonant(BSp,BS_files,Hdr_bse,prtvol,comm)
     133         [ +  + ]:           4 :        if(Bsp%do_ep_renorm) then
     134                 :           1 :          call exc_diago_resonant(BSp,BS_files,Hdr_bse,prtvol,comm,Epren=Epren,Kmesh=Kmesh,Cryst=Cryst,elph_lifetime=.TRUE.)
     135                 :             :        end if
     136                 :             :      else
     137         [ -  + ]:           1 :        if (Bsp%have_complex_ene) then
     138                 :             :          ! Solve Hv = ev with generic complex matrix.
     139                 :           0 :          call exc_diago_coupling(BSp,BS_files,Hdr_bse,prtvol,comm)
     140                 :             :        else
     141                 :             :          ! Solve generalized eigenvalue problem F Hbar with Hbar Hermitian definitive positive matrix.
     142                 :           1 :          call exc_diago_coupling_hegv(BSp,BS_files,Hdr_bse,prtvol,comm)
     143                 :             :        end if
     144                 :             :      end if
     145                 :             : 
     146                 :             :    case (BSE_ALGO_CG)
     147         [ +  - ]:           1 :      if (BSp%use_coupling==0) then
     148                 :           1 :        call exc_iterative_diago(Bsp,BS_files,Hdr_bse,prtvol,comm)
     149                 :             :      else
     150                 :           0 :        ABI_ERROR("CG + coupling not coded")
     151                 :             :      end if
     152                 :             : 
     153                 :             :    case default
     154                 :           0 :      write(msg,'(a,i0)')" Wrong value for Bsp%algorithm: ",Bsp%algorithm
     155      [ +  +  - ]:           6 :      ABI_ERROR(msg)
     156                 :             :    end select
     157                 :             :    !
     158         [ +  - ]:           6 :    if (my_rank==master) then
     159                 :           6 :      call QP_BSt%report_gap(header="QP bands",unit=std_out,gaps=gaps)
     160   [ +  -  -  +  :          19 :      gw_gap = MINVAL(gaps(2,:))
             -  -  +  + ]
     161                 :           6 :      call exc_print_eig(BSp,BS_files%out_eig,gw_gap,exc_gap)
     162                 :             :    end if
     163                 :           6 :    call xmpi_barrier(comm)
     164                 :             :    !
     165                 :             :  end if
     166                 :             : 
     167                 :           6 :  call build_spectra(BSp,BS_files,Cryst,Kmesh,KS_BSt,QP_BSt,Psps,Pawtab,Wfd,Hur,drude_plsmf,comm)
     168                 :             : 
     169                 :             :  ! Electron-phonon renormalization !
     170   [ +  +  +  +  :           6 :  if (BSp%algorithm == BSE_ALGO_DDIAGO .and. BSp%use_coupling == 0 .and. BSp%do_ep_renorm) then
                   +  + ]
     171                 :           1 :    call build_spectra(BSp,BS_files,Cryst,Kmesh,KS_BSt,QP_BSt,Psps,Pawtab,Wfd,Hur,drude_plsmf,comm,Epren=Epren)
     172                 :             :  end if
     173                 :             : 
     174                 :             :  DBG_EXIT("COLL")
     175                 :             : 
     176                 :           6 : end subroutine exc_diago_driver
     177                 :             : !!***
     178                 :             : 
     179                 :             : !----------------------------------------------------------------------
     180                 :             : 
     181                 :             : !!****f* m_exc_diago/exc_diago_resonant
     182                 :             : !! NAME
     183                 :             : !!  exc_diago_resonant
     184                 :             : !!
     185                 :             : !! FUNCTION
     186                 :             : !!  Calculates eigenvalues and eigenvectors of the Hermitian excitonic Hamiltonian (coupling is neglected).
     187                 :             : !!
     188                 :             : !! INPUTS
     189                 :             : !!  Bsp
     190                 :             : !!  BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.
     191                 :             : !!  comm=MPI communicator.
     192                 :             : !!  bseig_fname=The name of the output file
     193                 :             : !!  prtvol=Verbosity level.
     194                 :             : !!
     195                 :             : !! OUTPUT
     196                 :             : !!  Eigenvalues and eigenvectors are written on file bseig_fname
     197                 :             : !!
     198                 :             : !! SOURCE
     199                 :             : 
     200                 :           5 : subroutine exc_diago_resonant(Bsp,BS_files,Hdr_bse,prtvol,comm,Epren,Kmesh,Cryst,elph_lifetime)
     201                 :             : 
     202                 :             : !Arguments ------------------------------------
     203                 :             : !scalars
     204                 :             :  integer,intent(in) :: comm,prtvol
     205                 :             :  logical,optional,intent(in) :: elph_lifetime
     206                 :             :  type(excparam),intent(in) :: BSp
     207                 :             :  type(excfiles),intent(in) :: BS_files
     208                 :             :  type(Hdr_type),intent(in) :: Hdr_bse
     209                 :             :  type(eprenorms_t),optional,intent(in) :: Epren
     210                 :             :  type(kmesh_t),optional,intent(in) :: Kmesh
     211                 :             :  type(crystal_t),optional,intent(in) :: Cryst
     212                 :             : 
     213                 :             : !Local variables ------------------------------
     214                 :             : !scalars
     215                 :             :  integer,parameter :: master=0
     216                 :             :  integer :: ii,it,mi,hreso_unt,eig_unt,exc_size,neh1,neh2,j
     217                 :             :  integer :: nsppol,il,iu,mene_found,nstates
     218                 :             :  integer :: nprocs,my_rank,fform,nene_printed,ierr
     219                 :             :  real(dp) :: exc_gap,exc_maxene,abstol
     220                 :             :  real(dp) :: vl,vu
     221                 :             :  logical :: use_scalapack,do_full_diago,diagonal_is_real
     222                 :             :  character(len=500) :: msg
     223                 :             :  character(len=fnlen) :: hreso_fname,bseig_fname
     224                 :             : !arrays
     225                 :           5 :  real(dp),allocatable :: exc_ene(:)
     226                 :           5 :  complex(dp),allocatable :: exc_mat(:,:),exc_vec(:,:)
     227                 :             : #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
     228                 :             :  integer :: amode,mpi_fh,istwf_k,tbloc
     229                 :             :  integer(XMPI_OFFSET_KIND) :: ehdr_offset,fmarker
     230                 :             :  integer :: block_sizes(2,3),array_of_sizes(2),gsub(2,2)
     231                 :             :  logical,parameter :: is_fortran_file=.TRUE.
     232                 :             :  real(dp),external :: PDLAMCH
     233                 :             :  type(slkmat_dp_t) :: Slk_mat,Slk_vec
     234                 :             :  type(slk_processor_t) :: Slk_processor
     235                 :             : #endif
     236                 :             : 
     237                 :             :  integer :: ik, ic, iv, isppol, ireh, ep_ik, itemp
     238                 :             :  complex(dp) :: en
     239                 :             : 
     240                 :             :  real(dp) :: dksqmax
     241                 :           5 :  integer,allocatable :: bs2eph(:,:)
     242                 :             :  integer :: sppoldbl, timrev
     243                 :             :  logical :: do_ep_renorm, do_ep_lifetime
     244                 :             :  integer :: ntemp
     245                 :             :  character(len=4) :: ts
     246                 :           5 :  complex(dp),allocatable :: exc_vl(:,:),exc_ene_c(:)
     247                 :             :  complex(dp) :: ctemp
     248                 :             : !! complex(dp),allocatable :: ovlp(:,:)
     249                 :             : !************************************************************************
     250                 :             : 
     251                 :             :  DBG_ENTER("PERS")
     252                 :             : 
     253                 :           5 :  nprocs  = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
     254                 :             : 
     255         [ -  + ]:           5 :  if (BSp%have_complex_ene) then ! QP lifetimes are not included
     256                 :           0 :    ABI_ERROR("complex energies not coded yet")
     257                 :             :  end if
     258                 :             : 
     259   [ +  +  +  -  :          11 :  if (ANY(Bsp%nreh/=Bsp%nreh(1))) then
                   -  + ]
     260                 :           0 :    write(std_out,*)" Bsp%nreh: ",Bsp%nreh
     261                 :           0 :    write(msg,'(a)')" BSE code does not support different number of transitions for the two spin channels"
     262                 :           0 :    ABI_WARNING(msg)
     263                 :             :  end if
     264                 :             : 
     265                 :           5 :  nsppol   = Hdr_bse%nsppol
     266         [ +  + ]:          11 :  exc_size = SUM(BSp%nreh)
     267                 :           5 :  nstates  = BSp%nstates; do_full_diago=(Bsp%nstates==exc_size)
     268                 :             : 
     269                 :           5 :  neh1 = Bsp%nreh(1); neh2 = neh1
     270                 :             :  if (Hdr_bse%nsppol==2) neh2 = Bsp%nreh(2)
     271                 :             : 
     272                 :             :  ! Scalapack is disabled due to portability issues in slk_read
     273                 :             :  ! This part should be rewritten  with hdf5 + mpi-io
     274                 :             : 
     275                 :             :  use_scalapack = .FALSE.
     276                 :             : !#if defined HAVE_LINALG_SCALAPACK
     277                 :             : ! use_scalapack = (nprocs > 1)
     278                 :             : !#endif
     279                 :             :  if (use_scalapack .and. nsppol == 2) then
     280                 :             :    use_scalapack = .False.
     281                 :             :    ABI_WARNING("Scalapack with nsppol==2 not yet available. Using sequential version")
     282                 :             :  end if
     283                 :             : 
     284         [ -  + ]:           5 :  if (.not.use_scalapack .and. my_rank/=master) GOTO 10 ! Inversion is done by master only.
     285                 :             : 
     286         [ -  + ]:           5 :  nene_printed = MIN(32*nsppol,nstates); if (prtvol>10) nene_printed = nstates
     287                 :             : 
     288         [ +  + ]:           5 :  if (BS_files%in_hreso /= BSE_NOFILE) then
     289                 :           1 :    hreso_fname = BS_files%in_hreso
     290                 :             :  else
     291                 :           4 :    hreso_fname = BS_files%out_hreso
     292                 :             :  end if
     293                 :             : 
     294                 :           5 :  bseig_fname = BS_files%out_eig
     295         [ -  + ]:           5 :  if (BS_files%in_eig /= BSE_NOFILE) then
     296                 :           0 :    ABI_ERROR("BS_files%in_eig is defined!")
     297                 :             :  end if
     298                 :             : 
     299                 :           5 :  write(msg,'(a,i0)')' Direct diagonalization of the resonant excitonic Hamiltonian, Matrix size= ',exc_size
     300         [ +  + ]:          15 :  call wrtout([std_out, ab_out], msg)
     301                 :             : 
     302   [ -  +  +  -  :          15 :  ABI_MALLOC_OR_DIE(exc_ene,(exc_size), ierr)
          +  -  +  -  +  
             -  -  +  -  
                      + ]
     303   [ -  +  +  -  :          15 :  ABI_MALLOC_OR_DIE(exc_ene_c,(exc_size), ierr)
          +  -  +  -  +  
             -  -  +  -  
                      + ]
     304                 :             : 
     305                 :           5 :  do_ep_renorm = .FALSE.
     306                 :           5 :  ntemp = 1
     307                 :           5 :  do_ep_lifetime = .FALSE.
     308   [ +  +  +  + ]:           5 :  if(BSp%do_ep_renorm .and. present(Epren)) then
     309                 :           1 :    do_ep_renorm = .TRUE.
     310                 :           1 :    ntemp = Epren%ntemp
     311         [ +  - ]:           1 :    if(present(elph_lifetime)) then
     312                 :           1 :      do_ep_lifetime = elph_lifetime
     313                 :             :    end if
     314                 :             :  end if
     315                 :             : 
     316                 :             :  if (do_ep_renorm) then
     317         [ -  + ]:           1 :    ABI_CHECK(nsppol == 1, "Nsppol == 2 not supported with elphon renormalizations")
     318                 :             :  end if
     319                 :             : 
     320                 :             :  SELECT CASE (use_scalapack)
     321                 :             :  CASE (.FALSE.)
     322                 :             : 
     323                 :           5 :    write(msg,'(a)')". Using LAPACK sequential version. "
     324         [ +  + ]:          15 :    call wrtout([std_out, ab_out], msg)
     325                 :           5 :    write(msg,'(a,f8.1,a)')' Allocating excitonic eigenvalues. Memory required: ', exc_size*dp*b2Mb,' Mb. '
     326                 :           5 :    call wrtout(std_out, msg)
     327                 :             : 
     328                 :           5 :    write(msg,'(a,f8.1,a)')' Allocating excitonic hamiltonian.  Memory required: ',exc_size**2*dp*b2Mb,' Mb.'
     329                 :           5 :    call wrtout(std_out, msg, do_flush=.True.)
     330                 :             : 
     331   [ -  +  +  -  :          20 :    ABI_MALLOC_OR_DIE(exc_mat,(exc_size,exc_size), ierr)
          -  +  +  -  +  
          -  +  -  +  -  
             -  +  -  + ]
     332                 :             : 
     333         [ +  + ]:           5 :    if (do_ep_renorm) then
     334   [ -  +  +  -  :           3 :      ABI_MALLOC_OR_DIE(exc_vl,(exc_size,exc_size),ierr)
          -  +  +  -  +  
             -  -  +  -  
                      + ]
     335                 :             :    end if
     336                 :             :    !exc_mat = HUGE(zero)
     337                 :             :    !
     338                 :             :    ! Read data from file.
     339         [ -  + ]:           5 :    if (open_file(hreso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
     340                 :           0 :      ABI_ERROR(msg)
     341                 :             :    end if
     342                 :             :    !
     343                 :             :    ! Read the header and perform consistency checks.
     344                 :           5 :    call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
     345         [ -  + ]:           5 :    ABI_CHECK(ierr==0,"Fatal error, cannot continue")
     346                 :             :    !
     347                 :             :    ! Construct full resonant block using Hermiticity.
     348                 :           5 :    diagonal_is_real = .not.Bsp%have_complex_ene
     349                 :           5 :    call exc_read_rblock_fio(hreso_unt,diagonal_is_real,nsppol,Bsp%nreh,exc_size,exc_mat,ierr)
     350         [ -  + ]:           5 :    ABI_CHECK(ierr==0,"Fatal error, cannot continue")
     351                 :             : 
     352                 :           5 :    close(hreso_unt)
     353                 :             : 
     354         [ +  + ]:           5 :    if (do_ep_renorm) then
     355                 :           1 :      write(std_out,'(a)') "Mapping kpts from bse to eph"
     356                 :           1 :      sppoldbl = 1 !; if (any(Cryst%symafm == -1) .and. Epren%nsppol == 1) nsppoldbl=2
     357   [ -  +  +  -  :           3 :      ABI_MALLOC(bs2eph, (Kmesh%nbz*sppoldbl, 6))
          +  -  +  -  -  
                +  -  + ]
     358                 :           1 :      timrev = 1
     359                 :             :      call listkk(dksqmax, Cryst%gmet, bs2eph, Epren%kpts, Kmesh%bz, Epren%nkpt, Kmesh%nbz, Cryst%nsym, &
     360         [ +  - ]:           1 :         sppoldbl, Cryst%symafm, Cryst%symrel, timrev, xmpi_comm_self, use_symrec=.False.)
     361                 :             :    end if
     362                 :             : 
     363         [ +  + ]:          19 :    do itemp = 1, ntemp
     364                 :             : 
     365                 :             :      !TODO should find a way not to read again and again !
     366                 :             :      !  but without storing it twice !!!
     367                 :             :      !exc_mat = HUGE(zero)
     368                 :             :      !
     369                 :             :      ! Read data from file.
     370         [ -  + ]:          14 :      if (open_file(hreso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
     371                 :           0 :        ABI_ERROR(msg)
     372                 :             :      end if
     373                 :             :      !
     374                 :             :      ! Read the header and perform consistency checks.
     375                 :          14 :      call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
     376         [ -  + ]:          14 :      ABI_CHECK(ierr==0,"Fatal error, cannot continue")
     377                 :             :      !
     378                 :             :      ! Construct full resonant block using Hermiticity.
     379                 :          14 :      diagonal_is_real = .not.Bsp%have_complex_ene
     380                 :          14 :      call exc_read_rblock_fio(hreso_unt,diagonal_is_real,nsppol,Bsp%nreh,exc_size,exc_mat,ierr)
     381         [ -  + ]:          14 :      ABI_CHECK(ierr==0,"Fatal error, cannot continue")
     382                 :             : 
     383                 :          14 :      close(hreso_unt)
     384                 :             : 
     385                 :          14 :      bseig_fname = BS_files%out_eig
     386                 :             : 
     387         [ +  + ]:          14 :      if (do_ep_renorm) then
     388                 :          10 :        write(std_out,'(a,i4)') "Will perform elphon renormalization for itemp = ",itemp
     389                 :             : 
     390                 :          10 :        call int2char4(itemp,ts)
     391                 :             : 
     392         [ +  - ]:          10 :        bseig_fname = TRIM(BS_files%out_eig) // TRIM("_T") // ts
     393                 :             : 
     394                 :             :        ! Should patch the diagonal of exc_mat
     395                 :             : 
     396         [ +  + ]:          20 :        do isppol = 1, BSp%nsppol
     397         [ +  + ]:         980 :          do ireh = 1, BSp%nreh(isppol)
     398                 :         960 :            ic = BSp%Trans(ireh,isppol)%c
     399                 :         960 :            iv = BSp%Trans(ireh,isppol)%v
     400                 :         960 :            ik = BSp%Trans(ireh,isppol)%k ! In the full bz
     401                 :         960 :            en = BSp%Trans(ireh,isppol)%en
     402                 :             : 
     403                 :         960 :            ep_ik = bs2eph(ik,1)
     404                 :             : 
     405                 :             :            !TODO support multiple spins !
     406         [ -  + ]:         960 :            if(ABS(en - (Epren%eigens(ic,ep_ik,isppol)-Epren%eigens(iv,ep_ik,isppol)+BSp%mbpt_sciss)) > tol3) then
     407                 :           0 :              ABI_ERROR("Eigen from the transition does not correspond to the EP file !")
     408                 :             :            end if
     409                 :         960 :            exc_mat(ireh,ireh) = exc_mat(ireh,ireh) + (Epren%renorms(1,ic,ik,isppol,itemp) - Epren%renorms(1,iv,ik,isppol,itemp))
     410                 :             : 
     411                 :             :            ! Add lifetime
     412         [ +  - ]:         970 :            if(do_ep_lifetime) then
     413                 :             :              exc_mat(ireh,ireh) = exc_mat(ireh,ireh) - j_dpc*(Epren%linewidth(1,ic,ik,isppol,itemp) &
     414                 :         960 : &                + Epren%linewidth(1,iv,ik,isppol,itemp))
     415                 :             :            end if
     416                 :             : 
     417                 :             :          end do
     418                 :             :        end do
     419                 :             : 
     420                 :             :      end if
     421                 :             : 
     422         [ +  + ]:          14 :      if (do_full_diago) then
     423         [ +  + ]:          13 :        if(do_ep_renorm) then
     424                 :          10 :          call wrtout(std_out," Full diagonalization with XGEEV... ")
     425   [ -  +  +  -  :          30 :          ABI_MALLOC(exc_vec,(exc_size,exc_size))
          -  +  +  -  -  
                +  -  + ]
     426                 :          10 :          call xgeev('V','V',exc_size,exc_mat,exc_size,exc_ene_c,exc_vl,exc_size,exc_vec,exc_size)
     427   [ +  +  +  + ]:       93130 :          exc_mat(:,1:nstates) = exc_vec
     428         [ -  + ]:          10 :          ABI_FREE(exc_vec)
     429                 :             :        else
     430                 :           3 :          call wrtout(std_out," Full diagonalization with XHEEV... ")
     431                 :           3 :          call xheev("Vectors","Upper",exc_size,exc_mat,exc_ene)
     432         [ +  + ]:        1251 :          exc_ene_c(:) = exc_ene(:)
     433                 :             :        end if
     434                 :             :      else
     435                 :           1 :        call wrtout(std_out," Partial diagonalization with XHEEVX... ")
     436                 :           1 :        abstol=zero; il=1; iu=nstates
     437   [ -  +  +  -  :           4 :        ABI_MALLOC_OR_DIE(exc_vec,(exc_size,nstates),ierr)
          -  +  +  -  +  
          -  +  -  +  -  
             -  +  -  + ]
     438                 :           1 :        call xheevx("Vectors","Index","Upper",exc_size,exc_mat,vl,vu,il,iu,abstol,mene_found,exc_ene,exc_vec,exc_size)
     439   [ +  +  +  + ]:        3851 :        exc_mat(:,1:nstates) = exc_vec
     440         [ +  + ]:         385 :        exc_ene_c(:) = exc_ene(:)
     441         [ -  + ]:           1 :        ABI_FREE(exc_vec)
     442                 :             :      end if
     443                 :             :      !
     444                 :             :      ! ==============================================
     445                 :             :      ! === Now exc_mat contains the eigenvectors ====
     446                 :             :      ! ==============================================
     447                 :             : 
     448                 :             :      ! * Write the final results.
     449         [ +  - ]:          14 :      call wrtout(std_out,' Writing eigenvalues and eigenvectors to file: '//TRIM(bseig_fname))
     450                 :             : 
     451         [ -  + ]:          14 :      if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
     452                 :           0 :        ABI_ERROR(msg)
     453                 :             :      end if
     454                 :             : 
     455                 :             :      !!! !DBYG
     456                 :             :      !!! !Compute overlap matrix
     457                 :             :      !!! ABI_MALLOC(ovlp,(exc_size,exc_size))
     458                 :             :      !!! do mi=1,nstates
     459                 :             :      !!!   do ireh=1,nstates
     460                 :             :      !!!     ovlp(mi,ireh) = xdotc(exc_size,exc_vl(:,mi),1,exc_mat(:,ireh),1)
     461                 :             :      !!!     if(mi==ireh) then
     462                 :             :      !!!       !if(ABS(ovlp(mi,ireh)) < 0.999) then
     463                 :             :      !!!       !  write(*,*) "it,itp = ",mi,ireh,"ovlp = ",ovlp(mi,ireh)
     464                 :             :      !!!       !end if
     465                 :             :      !!!     else
     466                 :             :      !!!       if(ABS(ovlp(mi,ireh)) > 0.001) then
     467                 :             :      !!!         write(*,*) "it,itp = ",mi,ireh,"ovlp = ",ovlp(mi,ireh)
     468                 :             :      !!!       end if
     469                 :             :      !!!     end if
     470                 :             :      !!!   end do
     471                 :             :      !!! end do
     472                 :             :      !!! !call xgemm("C","N",exc_size,nstates,nstates,cone,exc_vl,exc_size,exc_mat,exc_size,czero,ovlp,nstates)
     473                 :             : 
     474                 :             :      !!! write(777,*) ovlp
     475                 :             :      !!! ABI_FREE(ovlp)
     476                 :             :      !!! !ENDDBYG
     477                 :             : 
     478                 :             :      !% fform = 1002 ! FIXME
     479                 :             :      !% call hdr_io_int(fform,Hdr_bse,2,eig_unt)
     480                 :             : 
     481                 :          14 :      write(eig_unt) do_ep_lifetime
     482                 :          14 :      write(eig_unt) exc_size, nstates
     483                 :          14 :      write(eig_unt) exc_ene_c(1:nstates)
     484         [ +  + ]:        2232 :      do mi=1,nstates
     485                 :        2218 :        write(eig_unt) exc_mat(1:exc_size,mi)
     486         [ +  + ]:        2232 :        if(do_ep_lifetime) then
     487                 :         960 :          write(eig_unt) exc_vl(1:exc_size,mi)
     488                 :             :        end if
     489                 :             :      end do
     490                 :             : 
     491                 :          47 :      close(eig_unt)
     492                 :             : 
     493                 :             :    end do ! itemp
     494                 :             : 
     495         [ -  + ]:           5 :    ABI_FREE(exc_mat)
     496         [ +  + ]:          15 :    if (do_ep_renorm) then
     497         [ -  + ]:           1 :      ABI_FREE(exc_vl)
     498         [ -  + ]:           1 :      ABI_FREE(bs2eph)
     499                 :             :    end if
     500                 :             : 
     501                 :             :  CASE (.TRUE.)
     502                 :             : 
     503                 :             : #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
     504                 :             :    if (nsppol==2) then
     505                 :             :      ABI_WARNING("nsppol==2 + scalapack not coded yet")
     506                 :             :    end if
     507                 :             : 
     508                 :             :    istwf_k=1; tbloc=50
     509                 :             :    write(msg,'(2(a,i0))')". Using scaLAPACK version with nprocs= ",nprocs,"; block size= ",tbloc
     510                 :             :    call wrtout([std_out, ab_out], msg)
     511                 :             : 
     512                 :             :    write(msg,'(a,f8.1,a)')' Allocating excitonic eigenvalues. Memory required: ',exc_size*dp*b2Mb,' Mb. '
     513                 :             :    call wrtout(std_out, msg)
     514                 :             :    !
     515                 :             :    ! Init scaLAPACK environment.
     516                 :             :    call Slk_processor%init(comm)
     517                 :             :    !
     518                 :             :    ! Init scaLAPACK matrices
     519                 :             :    call Slk_mat%init(exc_size,exc_size,Slk_processor,istwf_k)
     520                 :             :    call Slk_vec%init(exc_size,exc_size,Slk_processor,istwf_k)
     521                 :             :    !
     522                 :             :    ! Open the file with MPI-IO and skip the record.
     523                 :             :    amode=MPI_MODE_RDONLY
     524                 :             : 
     525                 :             :    call MPI_FILE_OPEN(comm, hreso_fname, amode, MPI_INFO_NULL, mpi_fh, ierr)
     526                 :             :    ABI_CHECK_MPI(ierr,"MPI_IO error opening file: "//TRIM(hreso_fname))
     527                 :             : 
     528                 :             :    ! Skip the header and find the offset for reading the matrix.
     529                 :             :    call exc_skip_bshdr_mpio(mpi_fh,xmpio_collective,ehdr_offset)
     530                 :             :    !
     531                 :             :    ! Read scaLAPACK matrix from the file.
     532                 :             :    if (nsppol==1) then
     533                 :             :      call slk_read(Slk_mat,"Upper","Hermitian",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset)
     534                 :             :    else
     535                 :             :      array_of_sizes = (/exc_size,exc_size/)
     536                 :             :      block_sizes(:,1) = (/neh1,neh1/)
     537                 :             :      block_sizes(:,2) = (/neh2,neh2/)
     538                 :             :      block_sizes(:,3) = (/neh1,neh2/)
     539                 :             :      ABI_ERROR("Not tested")
     540                 :             :      !call slk_read_from_blocks(Slk_mat,array_of_sizes,block_sizes,is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset)
     541                 :             :    end if
     542                 :             : 
     543                 :             :    call MPI_FILE_CLOSE(mpi_fh, ierr)
     544                 :             :    ABI_CHECK_MPI(ierr,"FILE_CLOSE")
     545                 :             : 
     546                 :             :    if (do_full_diago) then
     547                 :             :      call wrtout(std_out," Performing full diagonalization with scaLAPACK...")
     548                 :             :      call slk_mat%heev("Vectors","Upper",Slk_vec,exc_ene)
     549                 :             :    else
     550                 :             :      call wrtout(std_out," Performing partial diagonalization with scaLAPACK...")
     551                 :             :      il=1; iu=nstates; abstol=zero !ABSTOL = PDLAMCH(comm,'U')
     552                 :             :      call slk_mat%pzheevx("Vectors","Index","Upper",vl,vu,il,iu,abstol,Slk_vec,mene_found,exc_ene)
     553                 :             :    end if
     554                 :             : 
     555                 :             :    exc_ene_c(:) = exc_ene(:)
     556                 :             : 
     557                 :             :    call Slk_mat%free()
     558                 :             : 
     559                 :             :    call wrtout(std_out,' Writing eigenvalues/vectors to file: '//TRIM(bseig_fname), do_flush=.True.)
     560                 :             : 
     561                 :             :    ! Write distributed matrix on file bseig_fname with Fortran records.
     562                 :             :    if (my_rank==master) then ! Write exc eigenvalues. Vectors will be appended in slk_write.
     563                 :             :      if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
     564                 :             :        ABI_ERROR(msg)
     565                 :             :      end if
     566                 :             :      write(eig_unt) exc_size, nstates
     567                 :             :      write(eig_unt) exc_ene_c(1:nstates)
     568                 :             :      close(eig_unt)
     569                 :             :    end if
     570                 :             : 
     571                 :             :    call xmpi_barrier(comm)
     572                 :             :    !
     573                 :             :    ! Open the file with MPI-IO and skip the record.
     574                 :             :    amode=MPI_MODE_RDWR
     575                 :             : 
     576                 :             :    call MPI_FILE_OPEN(comm, bseig_fname, amode, MPI_INFO_NULL, mpi_fh, ierr)
     577                 :             :    ABI_CHECK_MPI(ierr,"MPI_IO error opening file: "//TRIM(hreso_fname))
     578                 :             : 
     579                 :             :    !call MPI_FILE_SYNC(mpi_fh,ierr)
     580                 :             : 
     581                 :             :    ehdr_offset = 0
     582                 :             :    call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,ierr)
     583                 :             :    call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,ierr)
     584                 :             : 
     585                 :             :    write(std_out,*)"Writing nstates ",nstates
     586                 :             :    gsub(:,1) = (/1,1/)
     587                 :             :    gsub(:,2) = (/exc_size,nstates/)
     588                 :             :    call slk_write(Slk_vec,"All",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset,glob_subarray=gsub)
     589                 :             : 
     590                 :             :    call MPI_FILE_CLOSE(mpi_fh, ierr)
     591                 :             :    ABI_CHECK_MPI(ierr,"FILE_CLOSE")
     592                 :             : 
     593                 :             :    call Slk_vec%free()
     594                 :             :    call Slk_processor%free()
     595                 :             :    call xmpi_barrier(comm)
     596                 :             : #else
     597                 :             :    ABI_BUG("You should not be here!")
     598                 :             : #endif
     599                 :             : 
     600                 :             :  END SELECT
     601                 :             : 
     602                 :             :  ! Order the eigenvalues
     603         [ +  + ]:        1354 :  do ii=nstates,2,-1
     604         [ +  + ]:      378583 :    do j=1,ii-1
     605         [ +  + ]:      378578 :      if (DBLE(exc_ene_c(j)) > DBLE(exc_ene_c(j+1))) then
     606                 :        3583 :        ctemp = exc_ene_c(j)
     607                 :        3583 :        exc_ene_c(j) = exc_ene_c(j+1)
     608                 :        3583 :        exc_ene_c(j+1) = ctemp
     609                 :             :      end if
     610                 :             :    end do
     611                 :             :  end do
     612                 :             : 
     613                 :             : 
     614                 :           5 :  write(msg,'(a,i4)')' Excitonic eigenvalues in eV up to n= ',nene_printed
     615         [ +  + ]:          15 :  call wrtout([std_out, ab_out], msg)
     616                 :             : 
     617         [ +  + ]:          27 :  do it=0,(nene_printed-1)/8
     618   [ +  -  +  + ]:         192 :    write(msg,'(8f10.5)') ( DBLE(exc_ene_c(ii))*Ha_eV, ii=1+it*8,MIN(it*8+8,nene_printed) )
     619         [ +  + ]:          71 :    call wrtout([std_out, ab_out], msg)
     620                 :             :  end do
     621                 :             : 
     622   [ +  -  -  +  :        1364 :  exc_gap    = MINVAL(DBLE(exc_ene_c(1:nstates)))
             -  -  +  + ]
     623   [ +  -  -  +  :        1364 :  exc_maxene = MAXVAL(DBLE(exc_ene_c(1:nstates)))
             -  -  +  + ]
     624                 :             : 
     625                 :           5 :  write(msg,'(a,2(a,f7.2,2a),a)')ch10,&
     626                 :           5 :   " First excitonic eigenvalue= ",exc_gap*Ha_eV,   " [eV]",ch10,&
     627                 :          10 :   " Last  excitonic eigenvalue= ",exc_maxene*Ha_eV," [eV]",ch10,ch10
     628         [ +  + ]:          15 :  call wrtout([std_out, ab_out], msg, do_flush=.True.)
     629                 :             : 
     630         [ -  + ]:           5 :  ABI_FREE(exc_ene_c)
     631         [ -  + ]:           5 :  ABI_FREE(exc_ene)
     632                 :             : 
     633                 :           5 : 10 call xmpi_barrier(comm)
     634                 :             : 
     635                 :             :  DBG_EXIT("PERS")
     636                 :             : 
     637   [ -  +  -  + ]:           5 : end subroutine exc_diago_resonant
     638                 :             : !!***
     639                 :             : 
     640                 :             : !----------------------------------------------------------------------
     641                 :             : 
     642                 :             : !!****f* m_exc_diago/exc_print_eig
     643                 :             : !! NAME
     644                 :             : !!  exc_print_eig
     645                 :             : !!
     646                 :             : !! FUNCTION
     647                 :             : !!  Print excitonic eigenvalues on std_out and ab_out.
     648                 :             : !!
     649                 :             : !! INPUTS
     650                 :             : !!  gw_gap=GW direct gap.
     651                 :             : !!  bseig_fname=The name of file containing eigenvalues and eigenvectors
     652                 :             : !!
     653                 :             : !! OUTPUT
     654                 :             : !!  exc_gap=Excitonic direct gap.
     655                 :             : !!  Additional info on the Excitonic spectrum are reported on standard output.
     656                 :             : !!
     657                 :             : !! SOURCE
     658                 :             : 
     659                 :           6 : subroutine exc_print_eig(BSp,bseig_fname,gw_gap,exc_gap)
     660                 :             : 
     661                 :             : !Arguments ------------------------------------
     662                 :             : !scalars
     663                 :             :  complex(dp),intent(in) :: gw_gap
     664                 :             :  complex(dp),intent(out) :: exc_gap
     665                 :             :  character(len=*),intent(in) :: bseig_fname
     666                 :             :  type(excparam),intent(in) :: BSp
     667                 :             : 
     668                 :             : !Local variables ------------------------------
     669                 :             : !scalars
     670                 :             :  integer :: nstates_read,ii,j,k,eig_unt,ieig,hsize_exp, hsize_read !,nstates
     671                 :             :  complex(dp) :: bind_energy,ctemp
     672                 :             :  character(len=500) :: msg
     673                 :             :  !type(Hdr_type) :: tmp_Hdr
     674                 :             : !arrays
     675                 :           6 :  integer,allocatable :: iperm(:)
     676                 :           6 :  real(dp),allocatable :: exc_rene(:)
     677                 :           6 :  complex(dp),allocatable :: exc_cene(:)
     678                 :             : !************************************************************************
     679                 :             : 
     680                 :           6 :  exc_gap = czero
     681                 :             : 
     682         [ -  + ]:           6 :  if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",status="old",action="read") /= 0) then
     683                 :           0 :    ABI_ERROR(msg)
     684                 :             :  end if
     685                 :             : 
     686                 :           6 :  read(eig_unt) ! do_ep_lifetime
     687                 :           6 :  read(eig_unt) hsize_read, nstates_read
     688                 :             : 
     689   [ +  +  +  + ]:          12 :  if (BSp%use_coupling==0) hsize_exp =   SUM(Bsp%nreh)
     690   [ +  +  +  + ]:           7 :  if (BSp%use_coupling>0)  hsize_exp = 2*SUM(Bsp%nreh)
     691                 :             : 
     692         [ -  + ]:           6 :  if (hsize_exp /= hsize_read) then
     693                 :           0 :    write(msg,'(2(a,i0))')" Wrong dimension: read: ",hsize_read," expected= ",hsize_exp
     694                 :           0 :    ABI_ERROR(msg)
     695                 :             :  end if
     696                 :             : 
     697   [ -  +  +  -  :          18 :  ABI_MALLOC(exc_cene,(nstates_read))
          +  -  +  -  -  
                +  -  + ]
     698                 :           6 :  read(eig_unt) exc_cene(:)
     699                 :             : 
     700   [ -  +  +  -  :          18 :  ABI_MALLOC(exc_rene,(nstates_read))
          +  -  +  -  -  
                +  -  + ]
     701   [ +  -  -  +  :        2048 :  exc_rene = DBLE(exc_cene)
             -  -  +  + ]
     702                 :             : 
     703   [ -  +  +  -  :          18 :  ABI_MALLOC(iperm,(nstates_read))
          +  -  +  -  -  
                +  -  + ]
     704   [ +  -  +  +  :        6126 :  iperm = (/(ii, ii=1,nstates_read)/)
          +  -  +  +  +  
          -  -  +  -  -  
                   +  + ]
     705                 :             : 
     706                 :           6 :  call sort_dp(nstates_read,exc_rene,iperm,tol6)
     707                 :             : 
     708         [ -  + ]:           6 :  ABI_FREE(exc_rene)
     709         [ -  + ]:           6 :  ABI_FREE(iperm)
     710                 :             : 
     711                 :             :  ! put in ascending order
     712         [ +  + ]:        2036 :  do ii=nstates_read,2,-1
     713         [ +  + ]:      669278 :    do j=1,ii-1
     714         [ +  - ]:      669272 :      if (DBLE(exc_cene(j)) > DBLE(exc_cene(j+1))) then
     715                 :           0 :        ctemp = exc_cene(j)
     716                 :           0 :        exc_cene(j) = exc_cene(j+1)
     717                 :           0 :        exc_cene(j+1) = ctemp
     718                 :             :      end if
     719                 :             :    end do
     720                 :             :  end do
     721                 :             : 
     722                 :           6 :  exc_gap = DCMPLX(ABS(DBLE(exc_cene(1))),AIMAG(exc_cene(1)))
     723                 :             : 
     724         [ +  + ]:        2042 :  do ii=1,nstates_read
     725         [ +  + ]:        2042 :    if (ABS(DBLE(exc_cene(ii))) < DBLE(exc_gap)) then
     726                 :         383 :      exc_gap = DCMPLX(ABS(DBLE(exc_cene(ii))),AIMAG(exc_cene(ii)))
     727                 :             :    end if
     728                 :             :  end do
     729                 :             : 
     730                 :           6 :  bind_energy = gw_gap - exc_gap
     731                 :             : 
     732                 :             :  write(msg,"(3(a,2f6.2,2a))")&
     733                 :           6 :   " GW  direct gap     ",gw_gap*Ha_eV,     " [eV] ",ch10,&
     734                 :           6 :   " EXC direct gap     ",exc_gap*Ha_eV,    " [eV] ",ch10,&
     735                 :          12 :   " EXC binding energy ",bind_energy*Ha_eV," [eV] ",ch10
     736         [ +  + ]:          18 :  call wrtout([std_out, ab_out], msg)
     737                 :             : 
     738                 :           6 :  msg=' Excitonic eigenvalues up to the GW energy gap [eV]'
     739         [ +  + ]:          18 :  call wrtout([std_out, ab_out], msg)
     740                 :             : 
     741         [ -  + ]:         390 :  do ii=1,nstates_read
     742         [ +  + ]:         390 :    if (DBLE(exc_cene(ii)) > zero) EXIT
     743                 :             :  end do
     744                 :             : 
     745         [ +  + ]:          96 :  do j=ii,nstates_read
     746         [ +  + ]:          96 :    if (DBLE(exc_cene(j)) > DBLE(gw_gap)) EXIT
     747                 :             :  end do
     748                 :           6 :  j=j-1
     749                 :             : 
     750         [ +  + ]:          96 :  do ieig=ii,j
     751                 :          90 :    write(msg,'(i3,a,2f6.2,a)')ieig," (",exc_cene(ieig)*Ha_eV,")"
     752         [ +  + ]:         276 :    call wrtout([std_out, ab_out], msg)
     753                 :             :  end do
     754                 :             : 
     755                 :           6 :  ii=ii-1
     756         [ +  + ]:          22 :  do j=ii,1,-1
     757         [ +  + ]:          22 :    if (ABS(DBLE(exc_cene(j))) > DBLE(gw_gap)) EXIT
     758                 :             :  end do
     759                 :           6 :  j=j+1
     760                 :             : 
     761                 :             :  ! This coding is not portable, write to ab_out has been disabled.
     762         [ +  + ]:           6 :  if (ii>0) then
     763         [ +  + ]:          17 :    do k=ii,j,-1
     764                 :          16 :      write(msg,'(i3,a,2f6.2,a)')k," (",exc_cene(k)*Ha_eV,")"
     765                 :          17 :      call wrtout(std_out, msg)
     766                 :             :    end do
     767                 :             :  end if
     768                 :             : 
     769                 :           6 :  ABI_FREE(exc_cene)
     770                 :             : 
     771                 :           6 :  close(eig_unt)
     772                 :             : 
     773                 :           6 : end subroutine exc_print_eig
     774                 :             : !!***
     775                 :             : 
     776                 :             : !----------------------------------------------------------------------
     777                 :             : 
     778                 :             : !!****f* m_exc_diago/exc_diago_coupling
     779                 :             : !! NAME
     780                 :             : !!  exc_diago_coupling
     781                 :             : !!
     782                 :             : !! FUNCTION
     783                 :             : !!  Calculate excitonic eigenvalues and eigenvectors by performing a direct diagonalization.
     784                 :             : !!  of the non Hermitian excitonic Hamiltoninan (resonant + coupling).
     785                 :             : !!
     786                 :             : !! INPUTS
     787                 :             : !!  bseig_fname=The name of the output file.
     788                 :             : !!  Bsp
     789                 :             : !!    neh=Rank of the resonant block of the Hamiltoninan (equal to the rank of the coupling part)
     790                 :             : !!  comm=MPI communicator.
     791                 :             : !!  BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.
     792                 :             : !!
     793                 :             : !! OUTPUT
     794                 :             : !!  Excitonic eigenvectors and eigenvalues are written on file BS_files%out_eig.
     795                 :             : !!
     796                 :             : !! SOURCE
     797                 :             : 
     798                 :           0 : subroutine exc_diago_coupling(Bsp,BS_files,Hdr_bse,prtvol,comm)
     799                 :             : 
     800                 :             : !Arguments ------------------------------------
     801                 :             : !scalars
     802                 :             :  integer,intent(in) :: comm,prtvol
     803                 :             :  type(excfiles),intent(in) :: BS_files
     804                 :             :  type(excparam),intent(in) :: BSp
     805                 :             :  type(Hdr_type),intent(in) :: Hdr_bse
     806                 :             : 
     807                 :             : !Local variables ------------------------------
     808                 :             : !scalars
     809                 :             :  integer,parameter :: master=0,ldvl=1
     810                 :             :  integer(i8b) :: bsize_ham
     811                 :             :  integer :: ii,exc_size,hreso_unt,hcoup_unt,eig_unt,nsppol,nstates
     812                 :             :  integer :: bsz,block,bs1,bs2,jj, fform,row_sign, mi,it,nprocs,my_rank !itp
     813                 :             :  integer :: nene_printed,ierr
     814                 :             :  real(dp) :: exc_gap,exc_maxene,temp
     815                 :             :  logical :: diago_is_real,do_full_diago, do_ep_lifetime
     816                 :             :  character(len=500) :: msg
     817                 :             :  character(len=fnlen) :: hreso_fname,hcoup_fname,bseig_fname
     818                 :             : !arrays
     819                 :           0 :  complex(dp),allocatable :: exc_ham(:,:),exc_rvect(:,:),exc_ene(:),ovlp(:,:), cbuff(:,:)
     820                 :             :  complex(dp) :: vl_dpc(ldvl,1)
     821                 :             : !************************************************************************
     822                 :             : 
     823                 :           0 :  my_rank = xmpi_comm_rank(comm); nprocs  = xmpi_comm_size(comm)
     824                 :             : 
     825                 :           0 :  nsppol = Hdr_bse%nsppol
     826         [ #  # ]:           0 :  if (nsppol==2) then
     827                 :           0 :    ABI_WARNING("nsppol==2 with coupling is still under development")
     828                 :             :  end if
     829                 :             : 
     830         [ #  # ]:           0 :  if (nprocs > 1) then
     831                 :           0 :    ABI_WARNING("Scalapack does not provide ZGEEV, diagonalization is done in sequential!")
     832                 :             :  end if
     833                 :             : 
     834         [ #  # ]:           0 :  exc_size = 2*SUM(BSp%nreh)
     835                 :           0 :  nstates  = BSp%nstates
     836                 :           0 :  do_full_diago = (exc_size==nstates)
     837         [ #  # ]:           0 :  ABI_CHECK(do_full_diago,"Partial diago not coded yet")
     838                 :             : 
     839                 :           0 :  bseig_fname = BS_files%out_eig
     840         [ #  # ]:           0 :  if (BS_files%in_eig /= BSE_NOFILE) then
     841                 :           0 :    ABI_ERROR("BS_files%in_eig is defined!")
     842                 :             :  end if
     843                 :             :  !
     844                 :             :  ! Only master performs the diagonalization since ScaLAPACK does not provide the parallel version of ZGEEV.
     845         [ #  # ]:           0 :  if (my_rank/=master) GOTO 10
     846                 :             : 
     847                 :           0 :  write(msg,'(a,i0)')' Direct diagonalization of the full excitonic Hamiltonian, Matrix size= ',exc_size
     848         [ #  # ]:           0 :  call wrtout([std_out, ab_out], msg)
     849                 :             : 
     850                 :           0 :  bsize_ham = 2*dp*exc_size**2
     851                 :           0 :  write(msg,'(a,f9.2,a)')' Allocating full excitonic Hamiltonian. Memory requested: ',bsize_ham*b2Gb,' Gb. '
     852                 :           0 :  call wrtout(std_out, msg)
     853                 :             : 
     854   [ #  #  #  #  :           0 :  ABI_MALLOC_OR_DIE(exc_ham,(exc_size,exc_size), ierr)
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     855                 :             : 
     856                 :             :  write(msg,'(3a,f8.1,3a,f8.1,a)')&
     857                 :           0 :   ' Allocating excitonic eigenvalues and eigenvectors. ',ch10,&
     858                 :           0 :   ' Memory-space requested: ',2*dp*exc_size*b2Gb,' Gb. ',ch10,&
     859                 :           0 :   ' Memory-space requested: ',bsize_ham*b2Gb,' Gb. '
     860                 :           0 :  call wrtout(std_out, msg)
     861                 :             : 
     862   [ #  #  #  #  :           0 :  ABI_MALLOC_OR_DIE(exc_ene,(exc_size), ierr)
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     863                 :             : 
     864         [ #  # ]:           0 :  if (BS_files%in_hreso /= BSE_NOFILE) then
     865                 :           0 :    hreso_fname = BS_files%in_hreso
     866                 :             :  else
     867                 :           0 :    hreso_fname = BS_files%out_hreso
     868                 :             :  end if
     869                 :             : 
     870         [ #  # ]:           0 :  call wrtout(std_out,' Reading resonant excitonic Hamiltonian from '//TRIM(hreso_fname))
     871                 :             : 
     872         [ #  # ]:           0 :  if (open_file(hreso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
     873                 :           0 :    ABI_ERROR(msg)
     874                 :             :  end if
     875                 :             :  !
     876                 :             :  ! Read the header and perform consistency checks.
     877                 :           0 :  call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
     878         [ #  # ]:           0 :  ABI_CHECK(ierr==0,"Wrong header")
     879                 :             :  !
     880                 :             :  ! Construct resonant and anti-resonant part of the excitonic Hamiltonian using Hermiticity. File is always in double precision.
     881                 :             :  ! Fill exc_ham with ( R  0 )
     882                 :             :  !                   ( 0 -R*)
     883                 :             : !BEGINDEBUG
     884   [ #  #  #  # ]:           0 :  exc_ham = HUGE(one)
     885                 :             : !ENDDEBUG
     886                 :             : 
     887                 :           0 :  row_sign=-1; diago_is_real=(.not.BSp%have_complex_ene)
     888                 :           0 :  call exc_fullh_from_blocks(hreso_unt,"Resonant",nsppol,row_sign,diago_is_real,BSp%nreh,exc_size,exc_ham)
     889                 :           0 :  close(hreso_unt)
     890                 :             : 
     891         [ #  # ]:           0 :  if (BS_files%in_hcoup /= BSE_NOFILE) then
     892                 :           0 :    hcoup_fname =  BS_files%in_hcoup
     893                 :             :  else
     894                 :           0 :    hcoup_fname =  BS_files%out_hcoup
     895                 :             :  end if
     896                 :             : 
     897         [ #  # ]:           0 :  call wrtout(std_out,' Reading coupling excitonic Hamiltonian from '//TRIM(hcoup_fname))
     898         [ #  # ]:           0 :  if (open_file(hcoup_fname,msg,newunit=hcoup_unt,form="unformatted",status="old",action="read") /= 0) then
     899                 :           0 :    ABI_ERROR(msg)
     900                 :             :  end if
     901                 :             :  !
     902                 :             :  ! Read the header and perform consistency checks.
     903                 :           0 :  call exc_read_bshdr(hcoup_unt,Bsp,fform,ierr)
     904         [ #  # ]:           0 :  ABI_CHECK(ierr==0,"Wrong header")
     905                 :             :  !
     906                 :             :  ! Fill exc_ham with ( 0  C) to have ( R   C )
     907                 :             :  !                   (-C* 0)         (-C* -R*)
     908                 :           0 :  row_sign=-1; diago_is_real=(.not.BSp%have_complex_ene) ! not used here
     909                 :           0 :  call exc_fullh_from_blocks(hcoup_unt,"Coupling",nsppol,row_sign,diago_is_real,BSp%nreh,exc_size,exc_ham)
     910                 :             : 
     911                 :             : !BEGINDEBUG
     912   [ #  #  #  #  :           0 :  if (ANY(exc_ham==HUGE(one))) then
             #  #  #  # ]
     913   [ #  #  #  #  :           0 :    write(msg,'(a,2(1x,i0))')"There is a bug in exc_fullh_from_blocks",COUNT(exc_ham==HUGE(one)),exc_size**2
                   #  # ]
     914                 :           0 :    ABI_WARNING(msg)
     915                 :           0 :    bsz = Bsp%nreh(1)
     916   [ #  #  #  #  :           0 :    ABI_MALLOC(cbuff,(bsz,bsz))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     917                 :           0 :    block=0
     918         [ #  # ]:           0 :    do jj=1,2*nsppol
     919         [ #  # ]:           0 :      do ii=1,2*nsppol
     920                 :           0 :        block=block+1
     921                 :           0 :        bs1 = (ii-1)*bsz+1
     922                 :           0 :        bs2 = (jj-1)*bsz+1
     923   [ #  #  #  #  :           0 :        cbuff = exc_ham(bs1:bs1+bsz-1,bs2:bs2+bsz-1)
          #  #  #  #  #  
                #  #  # ]
     924   [ #  #  #  #  :           0 :        if (ANY(cbuff==HUGE(one))) then
             #  #  #  # ]
     925   [ #  #  #  #  :           0 :          write(std_out,*)" for block ",ii,jj," found ",COUNT(cbuff==HUGE(one))," wrong entries"
                   #  # ]
     926                 :             :        end if
     927                 :             :      end do
     928                 :             :    end do
     929                 :             : 
     930         [ #  # ]:           0 :    ABI_FREE(cbuff)
     931                 :           0 :    ABI_ERROR("Cannot continue")
     932                 :             :  end if
     933                 :             : !ENDDEBUG
     934                 :             : 
     935                 :           0 :  close(hcoup_unt)
     936                 :             :  !
     937                 :             :  ! ======================================================
     938                 :             :  ! ==== Calculate right eigenvectors and eigenvalues ====
     939                 :             :  ! ======================================================
     940   [ #  #  #  #  :           0 :  ABI_MALLOC_OR_DIE(exc_rvect,(exc_size,exc_size), ierr)
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     941                 :             : 
     942         [ #  # ]:           0 :  if (do_full_diago) then
     943                 :           0 :    call wrtout(std_out,"Complete direct diagonalization with xgeev...")
     944                 :           0 :    call xgeev("No_left_eigen","Vectors",exc_size,exc_ham,exc_size,exc_ene,vl_dpc,ldvl,exc_rvect,exc_size)
     945                 :             :  else
     946                 :           0 :    ABI_ERROR("Not implemented error")
     947                 :             :  end if
     948                 :             : 
     949         [ #  # ]:           0 :  ABI_FREE(exc_ham)
     950                 :             : 
     951   [ #  #  #  #  :           0 :  exc_gap    = MINVAL(ABS(DBLE (exc_ene(1:nstates))))
             #  #  #  # ]
     952   [ #  #  #  #  :           0 :  exc_maxene = MAXVAL(ABS(DBLE (exc_ene(1:nstates))))
             #  #  #  # ]
     953   [ #  #  #  #  :           0 :  temp       = MAXVAL(ABS(AIMAG(exc_ene(1:nstates))))
             #  #  #  # ]
     954                 :             : 
     955                 :             :  write(msg,'(2(a,f7.2,2a),a,es9.2,2a)')&
     956                 :           0 :   " First excitonic eigenvalue: ",exc_gap*Ha_eV,   " [eV].",ch10,&
     957                 :           0 :   " Last  excitonic eigenvalue: ",exc_maxene*Ha_eV," [eV].",ch10,&
     958                 :           0 :   " Largest imaginary part:     ",temp*Ha_eV,      " [eV] ",ch10
     959         [ #  # ]:           0 :  call wrtout([std_out, ab_out], msg)
     960                 :             : 
     961         [ #  # ]:           0 :  nene_printed = MIN(32*nsppol,nstates); if (prtvol>10) nene_printed = nstates
     962                 :             : 
     963                 :             :  ! This is not portable as the the eigenvalues calculated by ZGEEV are not sorted.
     964                 :             :  ! Even two subsequent calculations with the same input on the same machine
     965                 :             :  ! might produce different orderings. Might sort the eigenvalues though, just for printing.
     966                 :             : 
     967                 :           0 :  write(msg,'(a,i0)')' Complex excitonic eigenvalues in eV up to n= ',nene_printed
     968                 :           0 :  call wrtout(std_out,msg)
     969                 :             : 
     970         [ #  # ]:           0 :  do it=0,(nene_printed-1)/4
     971   [ #  #  #  # ]:           0 :    write(msg,'(8f10.5)') ( exc_ene(ii)*Ha_eV, ii=1+it*4,MIN(it*4+4,nene_printed) )
     972                 :           0 :    call wrtout(std_out,msg)
     973                 :             :  end do
     974                 :             : 
     975         [ #  # ]:           0 :  call wrtout(std_out,ch10//" Writing eigenvalues and eigenvectors on file "//TRIM(bseig_fname))
     976                 :             : 
     977         [ #  # ]:           0 :  if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
     978                 :           0 :    ABI_ERROR(msg)
     979                 :             :  end if
     980                 :             : 
     981                 :             : !YG : new version with lifetime
     982                 :           0 :  do_ep_lifetime = .FALSE.
     983                 :           0 :  write(eig_unt) do_ep_lifetime
     984                 :             : 
     985                 :           0 :  write(eig_unt)exc_size,nstates
     986         [ #  # ]:           0 :  write(eig_unt)CMPLX(exc_ene(1:nstates),kind=dp)
     987         [ #  # ]:           0 :  do mi=1,nstates
     988                 :           0 :    write(eig_unt) exc_rvect(:,mi)
     989                 :             :  end do
     990                 :             : 
     991         [ #  # ]:           0 :  ABI_FREE(exc_ene)
     992                 :             : 
     993   [ #  #  #  #  :           0 :  ABI_MALLOC_OR_DIE(ovlp,(nstates,nstates), ierr)
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     994                 :             : 
     995                 :           0 :  call wrtout(std_out,' Calculating overlap matrix... ')
     996                 :             : 
     997                 :             :  !do itp=1,nstates
     998                 :             :  !  do it=1,nstates
     999                 :             :  !    ovlp(it,itp) = xdotc(exc_size,exc_rvect(:,it),1,exc_rvect(:,itp),1)
    1000                 :             :  !  end do
    1001                 :             :  !end do
    1002                 :           0 :  call xgemm("C","N",exc_size,nstates,nstates,cone,exc_rvect,exc_size,exc_rvect,exc_size,czero,ovlp,nstates)
    1003         [ #  # ]:           0 :  ABI_FREE(exc_rvect)
    1004                 :             : 
    1005                 :           0 :  call wrtout(std_out," Inverting overlap matrix... ")
    1006                 :             : 
    1007                 :             :  ! Version for generic complex matrix.
    1008                 :             :  !call xginv(ovlp,exc_size)
    1009                 :             : 
    1010                 :             :  ! The overlap is Hermitian definite positive.
    1011                 :           0 :  call xhdp_invert("Upper",ovlp,nstates)
    1012                 :           0 :  call hermitianize(ovlp,"Upper")
    1013                 :             : 
    1014         [ #  # ]:           0 :  call wrtout(std_out,' Writing overlap matrix S^-1 on file: '//TRIM(bseig_fname))
    1015                 :             : 
    1016         [ #  # ]:           0 :  do it=1,nstates
    1017         [ #  # ]:           0 :    write(eig_unt) CMPLX(ovlp(:,it),kind=dp)
    1018                 :             :  end do
    1019                 :             : 
    1020         [ #  # ]:           0 :  ABI_FREE(ovlp)
    1021                 :             : 
    1022                 :           0 :  close(eig_unt)
    1023                 :             : 
    1024                 :           0 : 10 call xmpi_barrier(comm)
    1025                 :             : 
    1026         [ #  # ]:           0 : end subroutine exc_diago_coupling
    1027                 :             : !!***
    1028                 :             : 
    1029                 :             : !----------------------------------------------------------------------
    1030                 :             : 
    1031                 :             : !!****f* m_exc_diago/exc_diago_coupling_hegv
    1032                 :             : !! NAME
    1033                 :             : !!  exc_diago_coupling_hegv
    1034                 :             : !!
    1035                 :             : !! FUNCTION
    1036                 :             : !!  Calculate excitonic eigenvalues and eigenvectors by performing a direct diagonalization.
    1037                 :             : !!  of the non Hermitian excitonic Hamiltonian (resonant + coupling).
    1038                 :             : !!
    1039                 :             : !! INPUTS
    1040                 :             : !!  bseig_fname=The name of the output file.
    1041                 :             : !!  Bsp
    1042                 :             : !!    neh=Rank of the resonant block of the Hamiltoninan (equal to the rank of the coupling part)
    1043                 :             : !!  comm=MPI communicator.
    1044                 :             : !!  BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.
    1045                 :             : !!
    1046                 :             : !! OUTPUT
    1047                 :             : !!  Excitonic eigenvectors and eigenvalues are written to file BS_files%out_eig.
    1048                 :             : !!
    1049                 :             : !! SOURCE
    1050                 :             : 
    1051                 :           1 : subroutine exc_diago_coupling_hegv(Bsp,BS_files,Hdr_bse,prtvol,comm)
    1052                 :             : 
    1053                 :             : !Arguments ------------------------------------
    1054                 :             : !scalars
    1055                 :             :  integer,intent(in) :: comm,prtvol
    1056                 :             :  type(excparam),intent(in) :: BSp
    1057                 :             :  type(excfiles),intent(in) :: BS_files
    1058                 :             :  type(Hdr_type),intent(in) :: Hdr_bse
    1059                 :             : 
    1060                 :             : !Local variables ------------------------------
    1061                 :             : !scalars
    1062                 :             :  integer,parameter :: master=0
    1063                 :             :  integer(i8b) :: bsize_ham
    1064                 :             :  integer :: itype,il,iu,spin,row1,row2,pad_r1,pad_r2,neh1,neh2
    1065                 :             :  integer :: ii,exc_size,hreso_unt,hcoup_unt,eig_unt
    1066                 :             :  integer :: fform,neig_found,nstates, mi,it,nprocs,my_rank
    1067                 :             :  integer :: nene_printed,nsppol,row_sign,ierr
    1068                 :             :  real(dp) :: exc_gap,exc_maxene,abstol,vl,vu
    1069                 :             :  character(len=500) :: msg
    1070                 :             :  character(len=fnlen) :: reso_fname,coup_fname,bseig_fname
    1071                 :             :  logical :: use_scalapack,do_full_diago,diago_is_real, do_ep_lifetime
    1072                 :             : !arrays
    1073                 :           1 :  real(dp),allocatable :: exc_ene(:) !,test_ene(:)
    1074                 :           1 :  complex(dp),allocatable :: exc_ham(:,:),exc_rvect(:,:),fmat(:,:),ovlp(:,:)
    1075                 :             : #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
    1076                 :             :  integer,parameter :: istwfk1=1
    1077                 :             :  integer :: amode,mpi_fh,tbloc,mene_found,mpi_err,my_nel,nsblocks
    1078                 :             :  integer :: iloc,jloc,iglob,jglob,etype,slk_mask_type,offset_err,el,rrs_kind,ccs_kind
    1079                 :             :  !integer :: max_r,max_c
    1080                 :             :  integer(XMPI_OFFSET_KIND) :: ehdr_offset,fmarker,my_offset
    1081                 :             :  integer :: gsub(2,2)
    1082                 :             :  logical,parameter :: is_fortran_file=.TRUE.
    1083                 :             :  complex(dp) :: ctmp
    1084                 :             :  integer,allocatable :: sub_block(:,:,:)
    1085                 :             :  integer,pointer :: myel2loc(:,:)
    1086                 :             :  complex(dp),allocatable :: tmp_cbuffer(:)
    1087                 :             :  character(50) :: uplo
    1088                 :             :  real(dp),external :: PDLAMCH
    1089                 :             :  type(slkmat_dp_t) :: Slk_F,Slk_Hbar,Slk_vec,Slk_ovlp !,Slk_tmp
    1090                 :             :  type(slk_processor_t) :: Slk_processor
    1091                 :             : #endif
    1092                 :             : !************************************************************************
    1093                 :             : 
    1094                 :           1 :  my_rank = xmpi_comm_rank(comm); nprocs  = xmpi_comm_size(comm)
    1095                 :             : 
    1096                 :           1 :  nsppol = Hdr_bse%nsppol
    1097         [ -  + ]:           1 :  if (nsppol==2) then
    1098                 :           0 :    ABI_WARNING("nsppol==2 is still under development!")
    1099                 :             :  end if
    1100                 :             : 
    1101                 :           1 :  neh1 = BSp%nreh(1); neh2=neh1
    1102                 :             :  if (nsppol==2) neh2 = BSp%nreh(2)
    1103                 :             : 
    1104         [ +  + ]:           2 :  exc_size = 2*SUM(Bsp%nreh)
    1105                 :           1 :  nstates  = Bsp%nstates
    1106                 :           1 :  do_full_diago=(nstates==exc_size)
    1107                 :             : 
    1108                 :           1 :  write(msg,'(a,i0)')'. Direct diagonalization of the full excitonic Hamiltonian, Matrix size= ',exc_size
    1109         [ +  + ]:           3 :  call wrtout([std_out, ab_out], msg)
    1110                 :             : 
    1111                 :           1 :  bseig_fname = BS_files%out_eig
    1112         [ -  + ]:           1 :  if (BS_files%in_eig /= BSE_NOFILE) then
    1113                 :           0 :    ABI_ERROR("BS_files%in_eig is defined!")
    1114                 :             :  end if
    1115                 :             : 
    1116         [ +  - ]:           1 :  if (BS_files%in_hreso /= BSE_NOFILE) then
    1117                 :           1 :    reso_fname = BS_files%in_hreso
    1118                 :             :  else
    1119                 :           0 :    reso_fname = BS_files%out_hreso
    1120                 :             :  end if
    1121         [ +  - ]:           1 :  call wrtout(std_out,' Reading resonant excitonic Hamiltonian from '//TRIM(reso_fname))
    1122                 :             : 
    1123         [ -  + ]:           1 :  if (BS_files%in_hcoup /= BSE_NOFILE) then
    1124                 :           0 :    coup_fname =  BS_files%in_hcoup
    1125                 :             :  else
    1126                 :           1 :    coup_fname =  BS_files%out_hcoup
    1127                 :             :  end if
    1128         [ +  - ]:           1 :  call wrtout(std_out,' Reading coupling excitonic Hamiltonian from '//TRIM(coup_fname))
    1129                 :             : 
    1130                 :             :  ! TODO: Reintegrate SCALAPACK: use new format
    1131                 :             : ! --- !ERROR
    1132                 :             : ! src_file: m_exc_diago.F90
    1133                 :             : ! src_line: 1398
    1134                 :             : ! mpi_rank: 0
    1135                 :             : ! message: |
    1136                 :             : !     SET_VIEW
    1137                 :             : !     Other I/O error , error stack:
    1138                 :             : !     ADIO_Set_view(48):  **iobadoverlap displacements of filetype must be in a monotonically nondecreasing order
    1139                 :             : ! ...
    1140                 :             : 
    1141                 :           1 :  use_scalapack = .FALSE.
    1142                 :             : #ifdef HAVE_LINALG_SCALAPACK
    1143                 :             :  ! This is alway false. I use this trick so that the second case below is always compiled
    1144                 :             :  ! to avoid regressions.
    1145                 :             :  use_scalapack = nprocs > 1 .and. nsppol > 5
    1146                 :             : #endif
    1147                 :             :  !use_scalapack = .FALSE.
    1148                 :             :  !use_scalapack = .TRUE.
    1149                 :             : 
    1150         [ -  + ]:           1 :  if (.not.use_scalapack .and. my_rank/=master) GOTO 10
    1151                 :             : 
    1152   [ -  +  +  -  :           3 :  ABI_MALLOC_OR_DIE(exc_ene,(exc_size), ierr)
          +  -  +  -  +  
             -  -  +  -  
                      + ]
    1153                 :             : 
    1154                 :             :  SELECT CASE (use_scalapack)
    1155                 :             : 
    1156                 :             :  CASE (.FALSE.)
    1157                 :           1 :    write(msg,'(a)')". Using LAPACK sequential version to solve FHv = ev with H positive definite. "
    1158         [ +  + ]:           3 :    call wrtout([std_out, ab_out], msg)
    1159                 :             : 
    1160                 :           1 :    bsize_ham = 2*dp*exc_size**2
    1161                 :           1 :    write(msg,'(a,f9.2,a)')' Allocating full excitonic Hamiltonian. Memory requested: ',2*bsize_ham*b2Gb,' Gb. '
    1162                 :           1 :    call wrtout(std_out, msg)
    1163                 :             : 
    1164   [ -  +  +  -  :           4 :    ABI_MALLOC_OR_DIE(exc_ham,(exc_size,exc_size), ierr)
          -  +  +  -  +  
          -  +  -  +  -  
             -  +  -  + ]
    1165   [ -  +  +  -  :           3 :    ABI_MALLOC_OR_DIE(fmat,(exc_size,exc_size), ierr)
          -  +  +  -  +  
             -  -  +  -  
                      + ]
    1166                 :             : 
    1167                 :             :    write(msg,'(3a,f8.1,3a,f8.1,a)')&
    1168                 :           1 :     ' Allocating excitonic eigenvalues and eigenvectors. ',ch10,&
    1169                 :           1 :     ' Memory-space requested: ',2*dp*exc_size*b2Gb,' Gb. ',ch10,&
    1170                 :           2 :     ' Memory-space requested: ',bsize_ham*b2Gb,' Gb. '
    1171                 :           1 :    call wrtout(std_out, msg)
    1172                 :             : 
    1173         [ -  + ]:           1 :    if (open_file(reso_fname,msg,newunit=hreso_unt,form="unformatted",status="old",action="read") /= 0) then
    1174                 :           0 :      ABI_ERROR(msg)
    1175                 :             :    end if
    1176                 :             :    !
    1177                 :             :    ! Read the header and perform consistency checks.
    1178                 :           1 :    call exc_read_bshdr(hreso_unt,Bsp,fform,ierr)
    1179         [ -  + ]:           1 :    ABI_CHECK(ierr==0,"Wrong header")
    1180                 :             :    !
    1181                 :             :    ! Construct Hbar = ( R   C )
    1182                 :             :    !                  ( C*  R*)
    1183                 :             :    !
    1184                 :           1 :    row_sign=+1; diago_is_real=(.not.BSp%have_complex_ene)
    1185                 :           1 :    call exc_fullh_from_blocks(hreso_unt,"Resonant",nsppol,row_sign,diago_is_real,Bsp%nreh,exc_size,exc_ham)
    1186                 :           1 :    close(hreso_unt)
    1187                 :             : 
    1188         [ -  + ]:           1 :    if (open_file(coup_fname,msg,newunit=hcoup_unt,form="unformatted",status="old",action="read") /= 0) then
    1189                 :           0 :      ABI_ERROR(msg)
    1190                 :             :    end if
    1191                 :             :    !
    1192                 :             :    ! Read the header and perform consistency checks.
    1193                 :           1 :    call exc_read_bshdr(hcoup_unt,Bsp,fform,ierr)
    1194         [ -  + ]:           1 :    ABI_CHECK(ierr==0,"Wrong header")
    1195                 :             : 
    1196                 :           1 :    row_sign=+1; diago_is_real=(.not.BSp%have_complex_ene) ! not used here.
    1197                 :           1 :    call exc_fullh_from_blocks(hcoup_unt,"Coupling",nsppol,row_sign,diago_is_real,Bsp%nreh,exc_size,exc_ham)
    1198                 :           1 :    close(hcoup_unt)
    1199                 :             : 
    1200                 :             : !#ifdef DEV_MG_DEBUG_THIS
    1201                 :             : !write(666)exc_ham
    1202                 :             : !#endif
    1203                 :             :    !
    1204                 :             :    ! Fill fmat = (1  0)
    1205                 :             :    !             (0 -1)
    1206   [ +  +  +  + ]:      590593 :    fmat = czero
    1207         [ +  + ]:           2 :    do spin=1,nsppol
    1208                 :           1 :      pad_r1 = (spin-1)*Bsp%nreh(1)
    1209         [ +  + ]:           2 :      pad_r2 = SUM(Bsp%nreh)
    1210         [ -  + ]:           1 :      if (spin==2) pad_r2 = pad_r2 + Bsp%nreh(1)
    1211         [ +  + ]:         386 :      do it=1,Bsp%nreh(spin)
    1212                 :         384 :        row1 = it + pad_r1
    1213                 :         384 :        row2 = it + pad_r2
    1214                 :         384 :        fmat(row1,row1) =  cone
    1215                 :         385 :        fmat(row2,row2) = -cone
    1216                 :             :      end do
    1217                 :             :    end do
    1218                 :             :    !
    1219                 :             :    ! ==================================================
    1220                 :             :    ! ==== Solve generalized EV problem F H u = e u ====
    1221                 :             :    ! ==================================================
    1222                 :             :    ! 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.
    1223                 :             :    !
    1224                 :           1 :    itype=2
    1225         [ +  - ]:           1 :    if (do_full_diago) then
    1226                 :           1 :      call wrtout(std_out," Full diagonalization with XHEGV... ")
    1227                 :           1 :      call xhegv(itype,"Vectors","Upper",exc_size,fmat,exc_ham,exc_ene)
    1228                 :             :    else
    1229                 :           0 :      call wrtout(std_out," Partial diagonalization with XHEGVX... ")
    1230   [ #  #  #  #  :           0 :      ABI_MALLOC_OR_DIE(exc_rvect,(exc_size,nstates), ierr)
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1231                 :           0 :      il=1; iu=1; abstol=zero
    1232                 :           0 :      call xhegvx(itype,"Vectors","All","Upper",exc_size,fmat,exc_ham,vl,vu,il,iu,abstol,neig_found,exc_ene,exc_rvect,exc_size)
    1233                 :             :    end if
    1234                 :             : 
    1235         [ -  + ]:           1 :    ABI_FREE(exc_ham)
    1236                 :             : 
    1237         [ +  - ]:           1 :    if (do_full_diago) then
    1238   [ -  +  +  -  :           4 :      ABI_MALLOC(exc_rvect,(exc_size,nstates))
          -  +  +  -  +  
          -  +  -  -  +  
             -  +  -  + ]
    1239   [ -  +  +  +  :      590594 :      exc_rvect = fmat(:,1:nstates)
                   +  + ]
    1240                 :             :    end if
    1241                 :             : 
    1242         [ -  + ]:           1 :    ABI_FREE(fmat)
    1243                 :             : 
    1244         [ +  - ]:           1 :    call wrtout(std_out," Writing eigenvalues and eigenvectors on file: "//TRIM(bseig_fname))
    1245                 :             : 
    1246         [ -  + ]:           1 :    if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
    1247                 :           0 :      ABI_ERROR(msg)
    1248                 :             :    end if
    1249                 :             : 
    1250                 :           1 :    do_ep_lifetime = .FALSE.
    1251                 :           1 :    write(eig_unt) do_ep_lifetime
    1252                 :           1 :    write(eig_unt) exc_size, nstates
    1253         [ +  + ]:         769 :    write(eig_unt) CMPLX(exc_ene(1:nstates),kind=dp)
    1254         [ +  + ]:         769 :    do mi=1,nstates
    1255         [ +  + ]:      590593 :      write(eig_unt) CMPLX(exc_rvect(:,mi),kind=dp)
    1256                 :             :    end do
    1257                 :             : 
    1258                 :             : !#ifdef DEV_MG_DEBUG_THIS
    1259                 :             : !   write(888)exc_rvect
    1260                 :             : !   write(888)exc_ene
    1261                 :             : !#endif
    1262                 :             : 
    1263   [ -  +  +  -  :           4 :    ABI_MALLOC_OR_DIE(ovlp,(nstates,nstates), ierr)
          -  +  +  -  +  
          -  +  -  +  -  
             -  +  -  + ]
    1264                 :             : 
    1265                 :           1 :    call wrtout(std_out,' Calculating overlap matrix...')
    1266                 :             : 
    1267                 :           1 :    call xgemm("C","N",exc_size,nstates,nstates,cone,exc_rvect,exc_size,exc_rvect,exc_size,czero,ovlp,nstates)
    1268         [ -  + ]:           1 :    ABI_FREE(exc_rvect)
    1269                 :             : 
    1270                 :             : !#ifdef DEV_MG_DEBUG_THIS
    1271                 :             : !write(667)ovlp
    1272                 :             : !#endif
    1273                 :             : 
    1274                 :           1 :    call wrtout(std_out," Inverting overlap matrix... ")
    1275                 :             :    !
    1276                 :             :    ! The overlap is Hermitian definite positive.
    1277                 :           1 :    call xhdp_invert("Upper",ovlp,nstates)
    1278                 :           1 :    call hermitianize(ovlp,"Upper")
    1279                 :             : 
    1280                 :             :    ! Version for generic complex matrix.
    1281                 :             :    !call xginv(ovlp,nstates)
    1282                 :             : 
    1283                 :             : !#ifdef DEV_MG_DEBUG_THIS
    1284                 :             : !write(668,*)ovlp
    1285                 :             : !#endif
    1286                 :             : 
    1287         [ +  - ]:           1 :    call wrtout(std_out,' Writing overlap matrix O^-1 on file: '//TRIM(bseig_fname))
    1288         [ +  + ]:         769 :    do it=1,nstates
    1289                 :         769 :      write(eig_unt) ovlp(:,it)
    1290                 :             :    end do
    1291                 :             : 
    1292         [ -  + ]:           1 :    ABI_FREE(ovlp)
    1293                 :           3 :    close(eig_unt)
    1294                 :             : 
    1295                 :             :  CASE (.TRUE.)
    1296                 :             : 
    1297                 :             : #if defined HAVE_LINALG_SCALAPACK && defined HAVE_MPI_IO
    1298                 :             :    !
    1299                 :             :    ! Init scaLAPACK matrix Hbar = ( R   C )
    1300                 :             :    !                              ( C*  R*)
    1301                 :             :    ! Battle plan:
    1302                 :             :    !   Here the reading is complicated by the fact that R and C are stored on two different files
    1303                 :             :    !   and moreover the matrices are in packed storage mode.
    1304                 :             :    !   For initializing the local part of the resonant and anti-resonant block we have to allocate
    1305                 :             :    !   a temporary buffer. Then we read the buffer from file and the corresponding elements of the
    1306                 :             :    !   scaLAPACK matrix are initialized taking into account the symmetries of R (Hermitian)
    1307                 :             :    !   The same procedure is used to read the coupling and the anti-coupling part (Symmetric).
    1308                 :             :    !
    1309                 :             :    tbloc=50
    1310                 :             :    write(msg,'(2(a,i0))')". Using MPI-IO + scaLAPACK version with nprocs= ",nprocs,"; block size= ",tbloc
    1311                 :             :    call wrtout([std_out, ab_out], msg, do_flush=.True.)
    1312                 :             :    !
    1313                 :             :    ! Init scaLAPACK environment.
    1314                 :             :    call Slk_processor%init(comm)
    1315                 :             :    !
    1316                 :             :    ! Open the Resonant file with MPI-IO and skip the record.
    1317                 :             :    amode=MPI_MODE_RDONLY
    1318                 :             : 
    1319                 :             :    call MPI_FILE_OPEN(comm, reso_fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
    1320                 :             :    msg = " MPI_IO error opening file: "//TRIM(reso_fname)
    1321                 :             :    ABI_CHECK_MPI(mpi_err,msg)
    1322                 :             :    !
    1323                 :             :    ! Skip the header and find the offset for reading the matrix.
    1324                 :             :    call exc_skip_bshdr_mpio(mpi_fh,xmpio_collective,ehdr_offset)
    1325                 :             :    !
    1326                 :             :    ! Read  = ( R  - )
    1327                 :             :    !         ( -  R*)
    1328                 :             :    call Slk_Hbar%init(exc_size,exc_size,Slk_processor,istwfk1)
    1329                 :             : 
    1330                 :             :    nullify(myel2loc)
    1331                 :             :    nsblocks=nsppol
    1332                 :             :    ABI_MALLOC(sub_block,(2,2,nsblocks))
    1333                 :             :    ABI_CHECK(nsppol==1,"nsppol==2 not coded yet")
    1334                 :             : 
    1335                 :             :    call slk_single_fview_read_mask(Slk_Hbar,rrs_of_glob,offset_in_file,nsblocks,sub_block,my_nel,myel2loc,etype,slk_mask_type,&
    1336                 :             : &    offset_err,is_fortran_file)
    1337                 :             : 
    1338                 :             :    if (offset_err/=0) then
    1339                 :             :      write(msg,"(3a)")&
    1340                 :             : &      " Global position index cannot be stored in a standard Fortran integer ",ch10,&
    1341                 :             : &      " Excitonic matrix cannot be read with a single MPI-IO call."
    1342                 :             :      ABI_ERROR(msg)
    1343                 :             :    end if
    1344                 :             : 
    1345                 :             :    ! Shift the offset because the view starts at the fist matrix element!
    1346                 :             :    ! TODO should rationalize the treatment of the offset
    1347                 :             :    my_offset = ehdr_offset + xmpio_bsize_frm
    1348                 :             :    call MPI_FILE_SET_VIEW(mpi_fh, my_offset, etype, slk_mask_type, 'native', MPI_INFO_NULL, mpi_err)
    1349                 :             :    ABI_CHECK_MPI(mpi_err,"SET_VIEW")
    1350                 :             : 
    1351                 :             :    call MPI_TYPE_FREE(slk_mask_type,mpi_err)
    1352                 :             :    ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
    1353                 :             :    !
    1354                 :             :    ! Read my portion of the R,-R* sublocks and store the values in a temporary buffer.
    1355                 :             :    ABI_MALLOC_OR_DIE(tmp_cbuffer,(my_nel), ierr)
    1356                 :             : 
    1357                 :             :    call xmpi_barrier(comm)
    1358                 :             : 
    1359                 :             :    call MPI_FILE_READ_ALL(mpi_fh, tmp_cbuffer, my_nel, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
    1360                 :             :    ABI_CHECK_MPI(mpi_err,"READ_ALL")
    1361                 :             :    !
    1362                 :             :    ! Symmetrize my Resonant part.
    1363                 :             :    do el=1,my_nel
    1364                 :             :      iloc = myel2loc(1,el)
    1365                 :             :      jloc = myel2loc(2,el)
    1366                 :             :      call Slk_Hbar%loc2glob(iloc,jloc,iglob,jglob)
    1367                 :             :      ctmp = tmp_cbuffer(el)
    1368                 :             :      if (iglob==jglob.and..not.Bsp%have_complex_ene) ctmp = DBLE(ctmp) ! Force the diagonal to be real.
    1369                 :             :      rrs_kind = rrs_of_glob(iglob,jglob,Slk_Hbar%size_global)
    1370                 :             :      if (rrs_kind==1.and.jglob<iglob) then ! Lower resonant
    1371                 :             :        ctmp = DCONJG(ctmp)
    1372                 :             :      else if (rrs_kind==-1.and.jglob>=iglob) then  ! Lower Anti-resonant (Diagonal is included).
    1373                 :             :        ctmp = DCONJG(ctmp)
    1374                 :             :      end if
    1375                 :             :      Slk_Hbar%buffer_cplx(iloc,jloc) = ctmp
    1376                 :             :    end do
    1377                 :             : 
    1378                 :             :    ABI_FREE(tmp_cbuffer)
    1379                 :             :    ABI_FREE(myel2loc)
    1380                 :             : 
    1381                 :             :    call MPI_FILE_CLOSE(mpi_fh, mpi_err)
    1382                 :             :    ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
    1383                 :             :    !
    1384                 :             :    ! Read  = ( -  C)
    1385                 :             :    !         (-C* -)
    1386                 :             :    !
    1387                 :             :    call MPI_FILE_OPEN(comm, coup_fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
    1388                 :             :    msg = " MPI_IO error opening file: "//TRIM(coup_fname)
    1389                 :             :    ABI_CHECK_MPI(mpi_err,msg)
    1390                 :             :    !
    1391                 :             :    ! Skip the header and find the offset for reading the matrix.
    1392                 :             :    call exc_skip_bshdr_mpio(mpi_fh,xmpio_collective,ehdr_offset)
    1393                 :             : 
    1394                 :             :    nullify(myel2loc)
    1395                 :             :    call slk_single_fview_read_mask(Slk_Hbar,ccs_of_glob,offset_in_file,nsblocks,sub_block,my_nel,myel2loc,etype,slk_mask_type,&
    1396                 :             : &    offset_err,is_fortran_file)
    1397                 :             : 
    1398                 :             :    ABI_FREE(sub_block)
    1399                 :             : 
    1400                 :             :    if (offset_err/=0) then
    1401                 :             :      write(msg,"(3a)")&
    1402                 :             : &      " Global position index cannot be stored in a standard Fortran integer ",ch10,&
    1403                 :             : &      " Excitonic matrix cannot be read with a single MPI-IO call."
    1404                 :             :      ABI_ERROR(msg)
    1405                 :             :    end if
    1406                 :             :    !
    1407                 :             :    ! Shift the offset because the view starts at the fist matrix element!
    1408                 :             :    ! TODO should rationalize the treatment of the offset so that the client code
    1409                 :             :    ! will automatically receive my_offset.
    1410                 :             :    my_offset = ehdr_offset + xmpio_bsize_frm
    1411                 :             :    call MPI_FILE_SET_VIEW(mpi_fh, my_offset, etype, slk_mask_type, 'native', MPI_INFO_NULL, mpi_err)
    1412                 :             :    ABI_CHECK_MPI(mpi_err,"SET_VIEW")
    1413                 :             : 
    1414                 :             :    call MPI_TYPE_FREE(slk_mask_type,mpi_err)
    1415                 :             :    ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
    1416                 :             :    !
    1417                 :             :    ! Read my portion of the C-C* blocks and store the values in a temporary buffer.
    1418                 :             :    ABI_MALLOC_OR_DIE(tmp_cbuffer,(my_nel), ierr)
    1419                 :             : 
    1420                 :             :    call MPI_FILE_READ_ALL(mpi_fh, tmp_cbuffer, my_nel, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
    1421                 :             :    ABI_CHECK_MPI(mpi_err,"READ_ALL")
    1422                 :             :    !
    1423                 :             :    ! Symmetrize my coupling part.
    1424                 :             :    ! Coupling block is symmetric => No symmetrization of the lower triangle.
    1425                 :             :    do el=1,my_nel
    1426                 :             :      iloc = myel2loc(1,el)
    1427                 :             :      jloc = myel2loc(2,el)
    1428                 :             :      call Slk_Hbar%loc2glob(iloc, jloc, iglob, jglob)
    1429                 :             :      ccs_kind = ccs_of_glob(iglob,jglob,Slk_Hbar%size_global)
    1430                 :             :      ctmp = tmp_cbuffer(el)
    1431                 :             :      if (ccs_kind==-1) ctmp = DCONJG(ctmp) ! Anti-coupling (Diagonal is included).
    1432                 :             :      Slk_Hbar%buffer_cplx(iloc,jloc) = ctmp
    1433                 :             :    end do
    1434                 :             : 
    1435                 :             :    ABI_FREE(tmp_cbuffer)
    1436                 :             :    ABI_FREE(myel2loc)
    1437                 :             : 
    1438                 :             :    !max_r=20; max_c=10
    1439                 :             :    !call print_arr(Slk_Hbar%buffer_cplx,max_r=max_r,max_c=max_c,unit=std_out)
    1440                 :             : 
    1441                 :             : !#ifdef DEV_MG_DEBUG_THIS
    1442                 :             : !   ABI_MALLOC(exc_ham,(exc_size,exc_size))
    1443                 :             : !   read(666)exc_ham
    1444                 :             : !
    1445                 :             : !   write(std_out,*)"Error Hbar: ",MAXVAL(ABS(exc_ham-Slk_Hbar%buffer_cplx))
    1446                 :             : !   ABI_FREE(exc_ham)
    1447                 :             : !#endif
    1448                 :             : 
    1449                 :             :    call MPI_FILE_CLOSE(mpi_fh, mpi_err)
    1450                 :             :    ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
    1451                 :             :    !
    1452                 :             :    ! Init scaLAPACK matrix F
    1453                 :             :    call Slk_F%init(exc_size,exc_size,Slk_processor,istwfk1)
    1454                 :             :    !
    1455                 :             :    ! Global F = (1  0)
    1456                 :             :    !            (0 -1)
    1457                 :             :    do jloc=1,Slk_F%size_local(2)
    1458                 :             :      do iloc=1,Slk_F%size_local(1)
    1459                 :             :        call Slk_F%loc2glob(iloc, jloc, iglob, jglob)
    1460                 :             :        if (iglob==jglob) then
    1461                 :             :          if (iglob<=SUM(Bsp%nreh)) then
    1462                 :             :            Slk_F%buffer_cplx(iloc,jloc) =  cone
    1463                 :             :          else
    1464                 :             :            Slk_F%buffer_cplx(iloc,jloc) = -cone
    1465                 :             :          end if
    1466                 :             :        else
    1467                 :             :          Slk_F%buffer_cplx(iloc,jloc) =  czero
    1468                 :             :        end if
    1469                 :             :      end do
    1470                 :             :    end do
    1471                 :             :    !
    1472                 :             :    ! ===========================================================
    1473                 :             :    ! ==== Solve generalized EV problem H u = F Hbar u = e u ====
    1474                 :             :    ! ===========================================================
    1475                 :             :    call Slk_vec%init(exc_size,exc_size,Slk_processor,istwfk1)
    1476                 :             :    !
    1477                 :             :    itype=2; vl=1; vu=1; il=1; iu=nstates
    1478                 :             :    abstol=zero !ABSTOL = PDLAMCH(comm,'U')
    1479                 :             : 
    1480                 :             : !#if 1
    1481                 :             :    if (do_full_diago) then
    1482                 :             :      call slk_F%pzhegvx(itype,"Vectors","All","Upper",Slk_Hbar,vl,vu,il,iu,abstol,Slk_vec,mene_found,exc_ene)
    1483                 :             :    else
    1484                 :             :      ABI_WARNING("Partial diago is still under testing")
    1485                 :             :      call slk_F%pzhegvx(itype,"Vectors","Index","Upper",Slk_Hbar,vl,vu,il,iu,abstol,Slk_vec,mene_found,exc_ene)
    1486                 :             :    end if
    1487                 :             : !#else
    1488                 :             : !   call xhegv(itype,"Vectors","Upper",exc_size,Slk_F%buffer_cplx,Slk_Hbar%buffer_cplx,exc_ene)
    1489                 :             : !   Slk_vec%buffer_cplx = Slk_F%buffer_cplx
    1490                 :             : !#endif
    1491                 :             : 
    1492                 :             : !#ifdef DEV_MG_DEBUG_THIS
    1493                 :             : !   if (PRODUCT(Slk_Hbar%size_local) /= exc_size**2) then
    1494                 :             : !     ABI_ERROR("Wrong size")
    1495                 :             : !   end if
    1496                 :             : !
    1497                 :             : !   ABI_MALLOC(exc_ham,(exc_size,exc_size))
    1498                 :             : !   read(888)exc_ham
    1499                 :             : !
    1500                 :             : !   write(std_out,*)"Error rvec: ",MAXVAL(ABS(exc_ham-Slk_vec%buffer_cplx))
    1501                 :             : !   ABI_FREE(exc_ham)
    1502                 :             : !
    1503                 :             : !   ABI_MALLOC(test_ene,(exc_size))
    1504                 :             : !   read(888)test_ene
    1505                 :             : !   write(std_out,*)"Error ene: ",MAXVAL(ABS(exc_ene-test_ene))
    1506                 :             : !   ABI_FREE(test_ene)
    1507                 :             : !#endif
    1508                 :             : 
    1509                 :             :    call Slk_F%free()
    1510                 :             :    call Slk_Hbar%free()
    1511                 :             : 
    1512                 :             :    call wrtout(std_out,ch10//" Writing eigenvalues and eigenvectors on file: "//TRIM(bseig_fname))
    1513                 :             :    !
    1514                 :             :    ! Open the file with Fortran-IO to write the Header.
    1515                 :             :    if (my_rank==master) then
    1516                 :             :      if (open_file(bseig_fname,msg,newunit=eig_unt,form="unformatted",action="write") /= 0) then
    1517                 :             :        ABI_ERROR(msg)
    1518                 :             :      end if
    1519                 :             : 
    1520                 :             :      write(eig_unt) exc_size,nstates
    1521                 :             :      write(eig_unt) CMPLX(exc_ene(1:nstates),kind=dp)
    1522                 :             :      !do mi=1,exc_size
    1523                 :             :      !  write(eig_unt) CMPLX(exc_rvect(:,mi),kind=dp)
    1524                 :             :      !end do
    1525                 :             :      close(eig_unt)
    1526                 :             :    end if
    1527                 :             :    !
    1528                 :             :    ! Open the file with MPI-IO and write the distributed eigevectors.
    1529                 :             :    call xmpi_barrier(comm)
    1530                 :             :    amode=MPI_MODE_RDWR
    1531                 :             :    call MPI_FILE_OPEN(comm, bseig_fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
    1532                 :             :    ABI_CHECK_MPI(mpi_err,"FILE_OPEN: "//TRIM(bseig_fname))
    1533                 :             :    !
    1534                 :             :    ! Skip the header and find the offset for writing the matrix.
    1535                 :             :    ehdr_offset=0
    1536                 :             :    !call hdr_mpio_skip(mpi_fh,fform,ehdr_offset)
    1537                 :             : 
    1538                 :             :    call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,mpi_err)
    1539                 :             :    write(std_out,*)" fmarker1 = ",fmarker
    1540                 :             :    call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,mpi_err)
    1541                 :             :    write(std_out,*)" fmarker2 = ",fmarker
    1542                 :             : 
    1543                 :             :    write(std_out,*)" Writing nstates ",nstates
    1544                 :             :    gsub(:,1) = (/1,1/)
    1545                 :             :    gsub(:,2) = (/exc_size,nstates/)
    1546                 :             :    call slk_write(Slk_vec,"All",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset,glob_subarray=gsub)
    1547                 :             : 
    1548                 :             :    call wrtout(std_out,' Calculating overlap matrix... ')
    1549                 :             :    if (.not.do_full_diago) then
    1550                 :             :      ABI_ERROR(" Init of Slk_ovlp is wrong")
    1551                 :             :    end if
    1552                 :             : 
    1553                 :             :    call Slk_ovlp%init(exc_size,exc_size,Slk_processor,istwfk1)
    1554                 :             : 
    1555                 :             :    ! Calculate the overlap matrix.
    1556                 :             :    ! FIXME
    1557                 :             :    ! The ESLL manual says that "matrices matrix1 and matrix2 must have no common elements;
    1558                 :             :    ! otherwise, results are unpredictable."
    1559                 :             :    ! However the official scaLAPACK documentation does not report this (severe) limitation.
    1560                 :             : 
    1561                 :             :    !call Slk_tmp%init(exc_size,exc_size,Slk_processor,istwfk1)
    1562                 :             :    !Slk_tmp%buffer_cplx = Slk_vec%buffer_cplx
    1563                 :             :    !call slk_pgemm("C","N",Slk_tmp,cone,Slk_vec,czero,Slk_ovlp)
    1564                 :             :    !call Slk_tmp%free()
    1565                 :             : 
    1566                 :             :    call slk_pgemm("C","N",Slk_vec,cone,Slk_vec,czero,Slk_ovlp)
    1567                 :             : 
    1568                 :             : !#ifdef DEV_MG_DEBUG_THIS
    1569                 :             : !   ABI_MALLOC(exc_ham,(exc_size,exc_size))
    1570                 :             : !   read(667)exc_ham
    1571                 :             : !
    1572                 :             : !   write(std_out,*)"Error Ovlp: ",MAXVAL(ABS(exc_ham-Slk_ovlp%buffer_cplx))
    1573                 :             : !   !Slk_ovlp%buffer_cplx = exc_ham
    1574                 :             : !#endif
    1575                 :             : 
    1576                 :             :    !max_r=20; max_c=10
    1577                 :             :    !call print_arr(Slk_ovlp%buffer_cplx,max_r=max_r,max_c=max_c,unit=std_out)
    1578                 :             : 
    1579                 :             :    call Slk_vec%free()
    1580                 :             : 
    1581                 :             :    call wrtout(std_out," Inverting overlap matrix... ")
    1582                 :             :    uplo="Upper"
    1583                 :             : 
    1584                 :             : !#if 0
    1585                 :             : !!DEBUG
    1586                 :             : !   call xhdp_invert(uplo,Slk_ovlp%buffer_cplx,exc_size)
    1587                 :             : !
    1588                 :             : !   !call slk_symmetrize(Slk_ovlp,uplo,"Hermitian")
    1589                 :             : !   call hermitianize(Slk_ovlp%buffer_cplx,uplo)
    1590                 :             : !
    1591                 :             : !   exc_ham = MATMUL(exc_ham,Slk_ovlp%buffer_cplx)
    1592                 :             : !   do it=1,exc_size
    1593                 :             : !     exc_ham(it,it) = exc_ham(it,it) - cone
    1594                 :             : !   end do
    1595                 :             : !
    1596                 :             : !   write(std_out,*)"Error Inversion: ",MAXVAL(ABS(exc_ham))
    1597                 :             : !   ABI_FREE(exc_ham)
    1598                 :             : !!END DEBUG
    1599                 :             : !
    1600                 :             : !#else
    1601                 :             :    ! call Slk_ovlp%hpd_invert(uplo)
    1602                 :             :    ! call hermitianize(Slk_ovlp%buffer_cplx,uplo)
    1603                 :             :    ! !call slk_symmetrize(Slk_ovlp,uplo,"Hermitian")
    1604                 :             : 
    1605                 :             :    call Slk_ovlp%invert()  ! Version for generic complex matrix.
    1606                 :             : !#endif
    1607                 :             : 
    1608                 :             : !#ifdef DEV_MG_DEBUG_THIS
    1609                 :             : !   ABI_MALLOC(exc_ham,(exc_size,exc_size))
    1610                 :             : !   read(668)exc_ham
    1611                 :             : !   write(std_out,*)"Error in Inv Ovlp: ",MAXVAL(ABS(exc_ham-Slk_ovlp%buffer_cplx))
    1612                 :             : !
    1613                 :             : !   !exc_ham = exc_ham-Slk_ovlp%buffer_cplx
    1614                 :             : !   !do it=1,exc_size
    1615                 :             : !   !  if ( MAXVAL(ABS(exc_ham(:,it))) > 0.1 ) write(std_out,*)"it: ",it,exc_ham(:,it)
    1616                 :             : !   !end do
    1617                 :             : !
    1618                 :             : !   !Slk_ovlp%buffer_cplx = exc_ham
    1619                 :             : !   ABI_FREE(exc_ham)
    1620                 :             : !
    1621                 :             : !   !write(std_out,*)"MAX ERR",MAXVAL(ABS(Slk_ovlp%buffer_cplx - TRANSPOSE(DCONJG(Slk_ovlp%buffer_cplx))))
    1622                 :             : !#endif
    1623                 :             : 
    1624                 :             :    call wrtout(std_out,' Writing overlap matrix S^-1 on file: '//TRIM(bseig_fname))
    1625                 :             : 
    1626                 :             :    call slk_write(Slk_ovlp,"All",is_fortran_file,mpi_fh=mpi_fh,offset=ehdr_offset)
    1627                 :             : 
    1628                 :             :    call MPI_FILE_CLOSE(mpi_fh, mpi_err)
    1629                 :             :    ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
    1630                 :             : 
    1631                 :             :    call Slk_ovlp%free()
    1632                 :             :    call Slk_processor%free()
    1633                 :             : #else
    1634                 :             :    ABI_BUG("You should not be here!")
    1635                 :             : #endif
    1636                 :             : 
    1637                 :             :  END SELECT
    1638                 :             : 
    1639   [ +  -  -  +  :         770 :  exc_gap    = MINVAL(ABS(exc_ene(1:nstates)))
             -  -  +  + ]
    1640   [ +  -  -  +  :         770 :  exc_maxene = MAXVAL(ABS(exc_ene(1:nstates)))
             -  -  +  + ]
    1641                 :             : 
    1642                 :             :  write(msg,'(2(a,f7.2,2a))')&
    1643                 :           1 :   " First excitonic eigenvalue: ",exc_gap*Ha_eV,   " [eV].",ch10,&
    1644                 :           2 :   " Last  excitonic eigenvalue: ",exc_maxene*Ha_eV," [eV].",ch10
    1645         [ +  + ]:           3 :  call wrtout([std_out, ab_out], msg)
    1646                 :             : 
    1647         [ -  + ]:           1 :  nene_printed = MIN(32*nsppol,nstates); if (prtvol>10) nene_printed = nstates
    1648                 :           1 :  write(msg,'(a,i0)')' Complex excitonic eigenvalues in eV up to n= ',nene_printed
    1649                 :           1 :  call wrtout(std_out, msg)
    1650                 :             : 
    1651         [ +  + ]:           9 :  do it=0,(nene_printed-1)/4
    1652   [ +  -  +  + ]:          40 :    write(msg,'(4f10.5)') ( exc_ene(ii)*Ha_eV, ii=1+it*4,MIN(it*4+4,nene_printed) )
    1653                 :           9 :    call wrtout(std_out, msg)
    1654                 :             :  end do
    1655                 :             : 
    1656         [ -  + ]:           1 :  ABI_FREE(exc_ene)
    1657                 :             : 
    1658                 :           1 : 10 call xmpi_barrier(comm)
    1659                 :             : 
    1660         [ -  + ]:           1 : end subroutine exc_diago_coupling_hegv
    1661                 :             : !!***
    1662                 :             : 
    1663                 :             : !----------------------------------------------------------------------
    1664                 :             : 
    1665                 :             : end module m_exc_diago
    1666                 :             : !!***
        

Generated by: LCOV version 2.3-1