LCOV - code coverage report
Current view: top level - src/71_bse - m_exc_spectra.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.5 % 511 478
Test Date: 2026-11-10 11:05:29 Functions: 100.0 % 9 9
Branches: 63.7 % 823 524

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_exc_spectra
       2                 :             : !! NAME
       3                 :             : !! m_exc_spectra
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  Routines to compute the macroscopic dielectric function in the Bethe-Salpeter code.
       7                 :             : !!
       8                 :             : !! COPYRIGHT
       9                 :             : !! Copyright (C) 2009-2026 ABINIT and EXC groups (L.Reining, V.Olevano, F.Sottile, S.Albrecht, G.Onida, M.Giantomassi, Y. Gillet)
      10                 :             : !!  This file is distributed under the terms of the
      11                 :             : !!  GNU General Public License, see ~abinit/COPYING
      12                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13                 :             : !!
      14                 :             : !! SOURCE
      15                 :             : 
      16                 :             : #if defined HAVE_CONFIG_H
      17                 :             : #include "config.h"
      18                 :             : #endif
      19                 :             : 
      20                 :             : #include "abi_common.h"
      21                 :             : 
      22                 :             : MODULE m_exc_spectra
      23                 :             : 
      24                 :             :  use, intrinsic :: iso_c_binding
      25                 :             :  use defs_basis
      26                 :             :  use m_bs_defs
      27                 :             :  use m_abicore
      28                 :             :  use m_xmpi
      29                 :             :  use m_errors
      30                 :             :  use netcdf
      31                 :             :  use m_nctk
      32                 :             :  use m_ebands
      33                 :             :  use m_hdr
      34                 :             : 
      35                 :             :  use defs_datatypes,    only : pseudopotential_type
      36                 :             :  use m_io_tools,        only : open_file
      37                 :             :  use m_fstrings,        only : toupper, strcat, sjoin, int2char4
      38                 :             :  use m_numeric_tools,   only : simpson_int, simpson_cplx
      39                 :             :  use m_hide_blas,       only : xdotu,xdotc
      40                 :             :  use m_special_funcs,   only : gaussian
      41                 :             :  use m_crystal,         only : crystal_t
      42                 :             :  use m_bz_mesh,         only : kmesh_t
      43                 :             :  use m_eprenorms,       only : eprenorms_t, renorm_bst
      44                 :             :  use m_pawtab,          only : pawtab_type
      45                 :             :  use m_paw_hr,          only : pawhur_t
      46                 :             :  use m_wfd,             only : wfdgw_t
      47                 :             :  !use m_bse_io,          only : exc_amplitude
      48                 :             :  use m_wfd_optic,       only : calc_optical_mels
      49                 :             : 
      50                 :             :  implicit none
      51                 :             : 
      52                 :             :  private
      53                 :             : 
      54                 :             :  public :: build_spectra           ! Driver routine for the computation of optical spectra.
      55                 :             :  public :: exc_write_data          ! This routine drives the writing of the files produced by the Bethe-Salpeter code.
      56                 :             :  public :: exc_eps_rpa             ! Build epsilon within RPA and GW.
      57                 :             :  public :: mdfs_ncwrite            ! Writes the MDF.nc file with the final results.
      58                 :             :  public :: exc_write_tensor        ! Write of complex dielectric tensor
      59                 :             :  !public :: exc_eps_resonant       ! Build the macroscopic dielectric function with excitonic effects.
      60                 :             : !!***
      61                 :             : 
      62                 :             : contains
      63                 :             : 
      64                 :             : !!****f* m_exc_spectra/build_spectra
      65                 :             : !! NAME
      66                 :             : !!  build_spectra
      67                 :             : !!
      68                 :             : !! FUNCTION
      69                 :             : !!  Driver routine for the computation of optical spectra.
      70                 :             : !!
      71                 :             : !! INPUTS
      72                 :             : !!  usepaw=1 for PAW calculations, 0 otherwise.
      73                 :             : !!  drude_plsmf=Drude plasma frequency.
      74                 :             : !!  Bsp<excparam>=Data type gathering the paramenters used for the Bethe-Salpeter calculation.
      75                 :             : !!    inclvkb=If different from 0, [Vnl,r] is included in the calculation of the matrix elements of the velocity operator.
      76                 :             : !!  BS_files<excfiles>=filenames used in the Bethe-Salpeter part.
      77                 :             : !!  Kmesh<kmesh_t>=the k-point sampling for the wave functions.
      78                 :             : !!  Cryst<crystal_t>=Structure defining the crystalline structure.
      79                 :             : !!  KS_BSt=The KS energies.
      80                 :             : !!  QP_BSt=The QP energies.
      81                 :             : !!  Psps <pseudopotential_type>=variables related to pseudopotentials.
      82                 :             : !!  Pawtab(Cryst%ntypat*usepaw)<pawtab_type>=PAW tabulated starting data
      83                 :             : !!  Hur(Cryst%natom*usepaw)<pawhur_t>=Only for PAW and DFT+U, quantities used to evaluate the commutator [H_u,r].
      84                 :             : !!  Wfd<wfdgw_t>=Handler for the wavefunctions.
      85                 :             : !!    nsppol=Number of independent spin polarizations.
      86                 :             : !!    nspinor=Number of spinorial components.
      87                 :             : !!  comm=MPI communicator.
      88                 :             : !!
      89                 :             : !! OUTPUT
      90                 :             : !!  No output. The routine calls specialized routines where the computation and the output of the spectra is done.
      91                 :             : !!
      92                 :             : !! SOURCE
      93                 :             : 
      94                 :           7 : subroutine build_spectra(BSp,BS_files,Cryst,Kmesh,KS_BSt,QP_BSt,Psps,Pawtab,Wfd,Hur,drude_plsmf,comm,Epren)
      95                 :             : 
      96                 :             : !Arguments ------------------------------------
      97                 :             : !scalars
      98                 :             :  integer,intent(in) :: comm
      99                 :             :  real(dp),intent(in) :: drude_plsmf
     100                 :             :  type(excparam),intent(in) :: BSp
     101                 :             :  type(excfiles),intent(in) :: BS_files
     102                 :             :  type(pseudopotential_type),intent(in) :: Psps
     103                 :             :  type(kmesh_t),intent(in) :: Kmesh
     104                 :             :  type(crystal_t),intent(in) :: Cryst
     105                 :             :  type(ebands_t),intent(in) :: KS_BSt,QP_BSt
     106                 :             :  type(wfdgw_t),intent(inout) :: Wfd
     107                 :             :  type(eprenorms_t),optional,intent(in) :: Epren
     108                 :             : !arrays
     109                 :             :  type(pawtab_type),intent(in) :: Pawtab(Cryst%ntypat*Wfd%usepaw)
     110                 :             :  type(pawhur_t),intent(in) :: Hur(Cryst%natom*Wfd%usepaw)
     111                 :             : 
     112                 :             : !Local variables ------------------------------
     113                 :             : !scalars
     114                 :             :  integer :: my_rank,master,iq,io,nsppol,lomo_min,max_band,ncid
     115                 :             :  integer :: itemp,ntemp
     116                 :             :  logical :: do_ep_renorm
     117                 :             :  real(dp) :: omegaev
     118                 :             :  complex(dp) :: ks_avg,gw_avg,exc_avg
     119                 :             :  character(len=4) :: ts
     120                 :             :  character(len=fnlen) :: path,prefix,filbseig, ost_fname
     121                 :             :  !character(len=500) :: msg
     122                 :           7 :  type(ebands_t) :: EPBSt, EP_QPBSt
     123                 :             : !arrays
     124                 :           7 :  real(dp),allocatable :: dos_exc(:),dos_gw(:),dos_ks(:)
     125                 :           7 :  complex(dp),allocatable :: eps_rpanlf(:,:),eps_gwnlf(:,:), eps_exc(:,:),opt_cvk(:,:,:,:,:)
     126                 :             : !************************************************************************
     127                 :             : 
     128                 :           7 :  my_rank = Wfd%my_rank
     129                 :           7 :  master  = Wfd%master
     130                 :           7 :  nsppol  = Wfd%nsppol
     131                 :             : 
     132                 :           7 :  do_ep_renorm = .False.
     133                 :           7 :  ntemp = 1
     134   [ +  +  +  + ]:           7 :  if (BSp%do_ep_renorm .and. PRESENT(Epren)) then
     135                 :           1 :    do_ep_renorm = .True.
     136                 :           1 :    ntemp = Epren%ntemp
     137                 :             :  end if
     138                 :             : 
     139                 :             :  ! =====================================================
     140                 :             :  ! === Calculate fcv(k)=<c k s|e^{-iqr}|v k s> in BZ ===
     141                 :             :  ! =====================================================
     142                 :           7 :  lomo_min=Bsp%lomo_min; max_band=Bsp%nbnds
     143   [ -  +  +  -  :          49 :  ABI_MALLOC(opt_cvk,(lomo_min:max_band,lomo_min:max_band,BSp%nkbz,nsppol,BSp%nq))
          -  +  +  -  -  
          +  +  -  -  +  
          +  -  -  +  +  
          -  +  -  +  -  
             -  +  -  + ]
     144                 :             : 
     145         [ +  + ]:          49 :  do iq=1,BSp%nq
     146                 :             :    call calc_optical_mels(Wfd,Kmesh,KS_BSt,Cryst,Psps,Pawtab,Hur,BSp%inclvkb,Bsp%lomo_spin,lomo_min,max_band,&
     147                 :          49 :                           BSp%nkbz,BSp%q(:,iq),opt_cvk(:,:,:,:,iq))
     148                 :             :  end do
     149                 :             :  !
     150                 :             :  ! ============================
     151                 :             :  ! ==== Make EPS EXCITONIC ====
     152                 :             :  ! ============================
     153         [ +  - ]:           7 :  if (my_rank==master) then ! Only master works.
     154                 :             : 
     155   [ -  +  +  -  :          28 :    ABI_MALLOC(eps_exc,(BSp%nomega,BSp%nq))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     156   [ -  +  +  -  :          21 :    ABI_MALLOC(dos_exc,(BSp%nomega))
          +  -  +  -  -  
                +  -  + ]
     157   [ -  +  +  -  :          21 :    ABI_MALLOC(eps_rpanlf,(BSp%nomega,BSp%nq))
          -  +  +  -  -  
                +  -  + ]
     158   [ -  +  +  -  :          14 :    ABI_MALLOC(dos_ks,(BSp%nomega))
             -  +  -  + ]
     159   [ -  +  +  -  :          21 :    ABI_MALLOC(eps_gwnlf ,(BSp%nomega,BSp%nq))
          -  +  +  -  -  
                +  -  + ]
     160   [ -  +  +  -  :          14 :    ABI_MALLOC(dos_gw,(BSp%nomega))
             -  +  -  + ]
     161                 :             : 
     162         [ +  + ]:          23 :    do itemp = 1, ntemp
     163                 :          16 :      call int2char4(itemp,ts)
     164                 :             : 
     165         [ +  + ]:          16 :      if(do_ep_renorm) then
     166                 :          10 :        prefix = TRIM("_T") // ts
     167                 :             :      else
     168                 :           6 :        prefix = ""
     169                 :             :      end if
     170                 :             : 
     171         [ +  - ]:          16 :      ost_fname = strcat(BS_files%out_basename,prefix,"_EXC_OST")
     172                 :             : 
     173                 :             :      !TODO for RPA
     174                 :          16 :      call KS_BST%copy(EPBSt)
     175                 :          16 :      call QP_BST%copy(EP_QPBSt)
     176                 :             : 
     177         [ -  + ]:          16 :      if (BS_files%in_eig /= BSE_NOFILE) then
     178         [ #  # ]:           0 :        filbseig = strcat(BS_files%in_eig,prefix)
     179                 :             :      else
     180         [ +  - ]:          16 :        filbseig = strcat(BS_files%out_eig,prefix)
     181                 :             :      end if
     182                 :             : 
     183         [ +  + ]:          16 :      if(do_ep_renorm) then
     184                 :             :        ! No scissor with KSBST
     185                 :          10 :        call renorm_bst(Epren, EPBSt, Cryst, itemp, do_lifetime=.TRUE.,do_check=.TRUE.)
     186                 :             : 
     187                 :          10 :        call renorm_bst(Epren, EP_QPBSt, Cryst, itemp, do_lifetime=.TRUE.,do_check=.FALSE.)
     188                 :             :      end if
     189                 :             : 
     190                 :             : 
     191         [ +  + ]:          16 :      if (BSp%use_coupling==0) then
     192                 :             :        call exc_eps_resonant(BSp,filbseig,ost_fname,lomo_min,max_band,BSp%nkbz,nsppol,opt_cvk,&
     193                 :          15 :         Cryst%ucvol,BSp%nomega,BSp%omega,eps_exc,dos_exc,elph_lifetime=do_ep_renorm)
     194                 :             :      else
     195                 :             :        call exc_eps_coupling(Bsp,BS_files,lomo_min,max_band,BSp%nkbz,nsppol,opt_cvk,&
     196                 :           1 :         Cryst%ucvol,BSp%nomega,BSp%omega,eps_exc,dos_exc)
     197                 :             :      end if
     198                 :             :      !
     199                 :             :      ! =======================================================
     200                 :             :      ! === Make EPS RPA and GW without local-field effects ===
     201                 :             :      ! =======================================================
     202                 :          16 :      call wrtout(std_out," Calculating RPA NLF and QP NLF epsilon")
     203                 :             : 
     204                 :             :      call exc_eps_rpa(BSp%nbnds,BSp%lomo_spin,Bsp%lomo_min,BSp%homo_spin,Kmesh,EPBSt,BSp%nq,nsppol,opt_cvk,&
     205                 :          16 :        Cryst%ucvol,BSp%broad,BSp%nomega,BSp%omega,eps_rpanlf,dos_ks)
     206                 :             : 
     207                 :             :      call exc_eps_rpa(BSp%nbnds,BSp%lomo_spin,Bsp%lomo_min,BSp%homo_spin,Kmesh,EP_QPBSt,BSp%nq,nsppol,opt_cvk,&
     208                 :          16 :       Cryst%ucvol,Bsp%broad,BSp%nomega,BSp%omega,eps_gwnlf,dos_gw)
     209                 :             :      !
     210                 :             :      ! =========================
     211                 :             :      ! === Write out Epsilon ===
     212                 :             :      ! =========================
     213                 :             :      !this is just for the automatic tests, It will be removed when fldiff
     214                 :             :      !will be able to compare two optical spectral
     215                 :          16 :      write(ab_out,*)" "
     216                 :          16 :      write(ab_out,*)"Macroscopic dielectric function:"
     217                 :          16 :      write(ab_out,*)"omega [eV] <KS_RPA_nlf>  <GW_RPA_nlf>  <BSE> "
     218         [ +  + ]:         176 :      do io=1,MIN(10,BSp%nomega)
     219                 :         160 :        omegaev = REAL(BSp%omega(io))*Ha_eV
     220         [ +  + ]:        1120 :        ks_avg  = SUM( eps_rpanlf(io,:)) / Bsp%nq
     221         [ +  + ]:        1120 :        gw_avg  = SUM( eps_gwnlf (io,:)) / Bsp%nq
     222         [ +  + ]:        1120 :        exc_avg = SUM( eps_exc   (io,:)) / Bsp%nq
     223                 :         176 :        write(ab_out,'(7f9.4)')omegaev,ks_avg,gw_avg,exc_avg
     224                 :             :      end do
     225                 :          16 :      write(ab_out,*)" "
     226                 :             : 
     227                 :             :      !
     228                 :             :      ! Master node writes final results on file.
     229                 :          16 :      call exc_write_data(BSp,BS_files,"RPA_NLF_MDF",eps_rpanlf,prefix=prefix,dos=dos_ks)
     230                 :          16 :      call exc_write_data(BSp,BS_files,"GW_NLF_MDF",eps_gwnlf,prefix=prefix,dos=dos_gw)
     231                 :          16 :      call exc_write_data(BSp,BS_files,"EXC_MDF",eps_exc,prefix=prefix,dos=dos_exc)
     232                 :             : 
     233                 :          16 :      call wrtout(std_out," Checking Kramers Kronig on Excitonic Macroscopic Epsilon")
     234   [ +  -  +  +  :       14240 :      call check_kramerskronig(BSp%nomega,REAL(BSp%omega),eps_exc(:,1))
                   -  + ]
     235                 :             : 
     236                 :          16 :      call wrtout(std_out," Checking Kramers Kronig on RPA NLF Macroscopic Epsilon")
     237   [ +  +  -  + ]:       14240 :      call check_kramerskronig(BSp%nomega,REAL(BSp%omega),eps_rpanlf(:,1))
     238                 :             : 
     239                 :          16 :      call wrtout(std_out," Checking Kramers Kronig on GW NLF Macroscopic Epsilon")
     240   [ +  +  -  + ]:       14240 :      call check_kramerskronig(BSp%nomega,REAL(BSp%omega),eps_gwnlf(:,1))
     241                 :             : 
     242                 :          16 :      call wrtout(std_out," Checking f-sum rule on Excitonic Macroscopic Epsilon")
     243                 :             : 
     244         [ +  - ]:          16 :      if (BSp%exchange_term>0) then
     245                 :          16 :        ABI_COMMENT(' f-sum rule should be checked without LF')
     246                 :             :      end if
     247   [ +  +  +  -  :       28464 :      call check_fsumrule(BSp%nomega,REAL(BSp%omega),AIMAG(eps_exc(:,1)),drude_plsmf)
          +  +  -  +  -  
                      + ]
     248                 :             : 
     249                 :          16 :      call wrtout(std_out," Checking f-sum rule on RPA NLF Macroscopic Epsilon")
     250   [ +  +  +  +  :       28464 :      call check_fsumrule(BSp%nomega,REAL(BSp%omega),AIMAG(eps_rpanlf(:,1)),drude_plsmf)
             -  +  -  + ]
     251                 :             : 
     252                 :          16 :      call wrtout(std_out," Checking f-sum rule on GW NLF Macroscopic Epsilon")
     253   [ +  +  +  +  :       28464 :      call check_fsumrule(BSp%nomega,REAL(BSp%omega),AIMAG(eps_gwnlf(:,1)),drude_plsmf)
             -  +  -  + ]
     254                 :             : 
     255         [ +  - ]:          16 :      path = strcat(BS_files%out_basename, strcat(prefix,"_MDF.nc"))
     256         [ -  + ]:          16 :      NCF_CHECK_MSG(nctk_open_create(ncid, path, xmpi_comm_self), sjoin("Creating MDF file:", path))
     257         [ -  + ]:          16 :      NCF_CHECK(cryst%ncwrite(ncid))
     258         [ -  + ]:          16 :      NCF_CHECK(QP_BSt%ncwrite(ncid))
     259                 :             :      ! Write dielectric functions.
     260                 :          16 :      call mdfs_ncwrite(ncid, Bsp, eps_exc,eps_rpanlf,eps_gwnlf)
     261         [ -  + ]:          16 :      NCF_CHECK(nf90_close(ncid))
     262                 :             : 
     263                 :             :      !TODO
     264                 :          16 :      call EPBSt%free()
     265                 :          23 :      call EP_QPBSt%free()
     266                 :             :    end do
     267                 :             : 
     268         [ -  + ]:           7 :    ABI_FREE(eps_rpanlf)
     269         [ -  + ]:           7 :    ABI_FREE(eps_gwnlf)
     270         [ -  + ]:           7 :    ABI_FREE(eps_exc)
     271         [ -  + ]:           7 :    ABI_FREE(dos_exc)
     272         [ -  + ]:           7 :    ABI_FREE(dos_ks)
     273         [ -  + ]:           7 :    ABI_FREE(dos_gw)
     274                 :             :  end if ! my_rank==master
     275                 :             : 
     276         [ -  + ]:           7 :  ABI_FREE(opt_cvk)
     277                 :             : 
     278                 :           7 :  call xmpi_barrier(comm)
     279                 :             : 
     280   [ -  +  -  +  :           7 : end subroutine build_spectra
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     281                 :             : !!***
     282                 :             : 
     283                 :             : !----------------------------------------------------------------------
     284                 :             : 
     285                 :             : !!****f* m_exc_spectra/exc_write_data
     286                 :             : !! NAME
     287                 :             : !!  exc_write_data
     288                 :             : !!
     289                 :             : !! FUNCTION
     290                 :             : !!  This routine drives the writing of the files produced by the Bethe-Salpeter code.
     291                 :             : !!
     292                 :             : !! INPUTS
     293                 :             : !! BSp<excparam>=Bethe-Salpeter Parameters.
     294                 :             : !! what= "EXC_MDF"
     295                 :             : !!       "RPA_NLF_MDF"
     296                 :             : !!       "GW_NLF_MDF"
     297                 :             : !! [dos(nomega)]
     298                 :             : !!
     299                 :             : !! OUTPUT
     300                 :             : !!  Only writing.
     301                 :             : !!
     302                 :             : !! SIDE EFFECTS
     303                 :             : !!  eps(BSp%nomega,BSp%nq) = Macroscopic dielectric function to be written.
     304                 :             : !!
     305                 :             : !! SOURCE
     306                 :             : 
     307                 :         132 : subroutine exc_write_data(BSp,BS_files,what,eps,prefix,dos)
     308                 :             : 
     309                 :             : !Arguments ------------------------------------
     310                 :             : !scalars
     311                 :             :  character(len=*),intent(in) :: what
     312                 :             :  type(excparam),intent(in) :: BSp
     313                 :             :  type(excfiles),intent(in) :: BS_files
     314                 :             :  character(len=*),optional,intent(in) :: prefix
     315                 :             : !arrays
     316                 :             :  real(dp),optional,intent(in) :: dos(BSp%nomega)
     317                 :             :  complex(dp),intent(in) :: eps(BSp%nomega,BSp%nq)
     318                 :             : 
     319                 :             : !Local variables ------------------------------
     320                 :             : !scalars
     321                 :             :  integer :: io,iq,funt
     322                 :             :  real(dp) :: omegaev,step
     323                 :             :  !real(dp),parameter :: SMALL=5.0d-99
     324                 :             : !arrays
     325                 :         264 :  real(dp) :: int_dos(BSp%nomega)
     326                 :         264 :  real(dp) :: tmp_eps(2,BSp%nq)
     327                 :             :  character(len=500) :: lf_type,block_type,wgg_type,frm,str_type,msg
     328                 :             :  character(len=fnlen) :: fname
     329                 :             : !************************************************************************
     330                 :             : 
     331         [ +  - ]:         132 :  if (PRESENT(prefix)) then
     332         [ +  - ]:         132 :    fname = strcat(BS_files%out_basename,prefix,'_',toupper(what))
     333                 :             :  else
     334         [ #  # ]:           0 :    fname = strcat(BS_files%out_basename,'_',toupper(what))
     335                 :             :  end if
     336                 :             : 
     337         [ -  + ]:         132 :  if (open_file(fname,msg,newunit=funt,form="formatted", action="write") /= 0) then
     338                 :           0 :    ABI_ERROR(msg)
     339                 :             :  end if
     340                 :             : 
     341                 :         308 :  select case (toupper(what))
     342                 :             :  case ("EXC_MDF")
     343         [ +  - ]:          44 :    call wrtout(ab_out," Writing EXC Macroscopic dielectric function to file: "//trim(fname))
     344                 :             : 
     345                 :          44 :    write(funt,'("# Macroscopic dielectric function obtained with the BS equation.")')
     346                 :             : 
     347                 :          44 :    lf_type = 'WITHOUT LOCAL FIELD EFFECTS'
     348         [ +  - ]:          44 :    if (BSp%exchange_term>0) lf_type='LOCAL FIELD EFFECTS INCLUDED'
     349                 :          44 :    call bsp%calctype2str(str_type)
     350                 :          44 :    write(funt,'("# ",a,"     " ,a)') TRIM(str_type), TRIM(lf_type)
     351                 :             : 
     352                 :          44 :    block_type = 'RESONANT-ONLY calculation'
     353         [ +  + ]:          44 :    if (BSp%use_coupling>0) block_type = 'RESONANT+COUPLING calculation'
     354                 :          44 :    write(funt,'("# ",a)') TRIM(block_type)
     355                 :             : 
     356         [ +  - ]:          44 :    if (BSp%use_coulomb_term) then
     357                 :          44 :      wgg_type = "Coulomb term constructed with full W(G1,G2)"
     358         [ +  + ]:          44 :      if ( BSp%use_diagonal_Wgg ) wgg_type = "Coulomb term constructed with diagonal approximation W(G1,G1)"
     359                 :          44 :      write(funt,'("# ",a)') TRIM(wgg_type)
     360                 :             :    end if
     361                 :             : 
     362                 :          44 :    write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]'
     363                 :             : 
     364                 :             :  case ("RPA_NLF_MDF")
     365         [ +  - ]:          44 :    call wrtout(ab_out," Writing KS-RPA macroscopic dielectric function without local fields to file: "//trim(fname))
     366                 :          44 :    write(funt,'("# RPA macroscopic dielectric function without local fields")')
     367                 :             : 
     368                 :             :  case ("GW_NLF_MDF")
     369         [ +  - ]:          44 :    call wrtout(ab_out," Writing GW-RPA macroscopic dielectric function without local fields to file: "//trim(fname))
     370                 :             : 
     371                 :          44 :    write(funt,'("# GW Macroscopic dielectric function without local field effects ")')
     372                 :          44 :    write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]'
     373                 :             : 
     374                 :             :  case default
     375   [ +  +  +  -  :         132 :    ABI_ERROR("Unknown value for what: "//trim(what))
                   -  - ]
     376                 :             :  end select
     377                 :             : 
     378                 :             :  ! Paramaters common to the different calculations.
     379         [ +  + ]:         132 :  if (BSp%algorithm /= BSE_ALGO_HAYDOCK) then
     380                 :          48 :    write(funt,'(a,i0)')"# nstates included in the diagonalization = ",BSp%nstates
     381                 :             :  end if
     382                 :             : 
     383         [ +  + ]:         132 :  if (BSp%algorithm == BSE_ALGO_HAYDOCK) then
     384                 :          84 :    write(funt,'(a,2f7.4)')'# Tolerance = ',BSp%haydock_tol
     385                 :             :  end if
     386                 :             : 
     387                 :         132 :  write(funt,'(a,i0)')"# npweps  = ",BSp%npweps
     388                 :         132 :  write(funt,'(a,i0)')"# npwwfn  = ",BSp%npwwfn
     389                 :         132 :  write(funt,'(a,i0)')"# nbands  = ",BSp%nbnds
     390                 :         132 :  write(funt,'(a,i0)')"# loband  = ",BSp%lomo_spin(1)
     391         [ +  + ]:         132 :  if (Bsp%nsppol==2) write(funt,'(a,i0)')"# loband(spin=2) = ",BSp%lomo_spin(2)
     392                 :         132 :  write(funt,'(a,i0)')"# nkibz   = ",BSp%nkibz
     393                 :         132 :  write(funt,'(a,i0)')"# nkbz    = ",BSp%nkbz
     394                 :         132 :  write(funt,'(a,f7.4,a)')'# Lorentzian broadening = ',BSp%broad*Ha_eV,' [eV]'
     395                 :             : 
     396                 :             :  ! Write the list of q-points.
     397                 :         132 :  write(funt,'(a)')"# List of q-points for the optical limit:"
     398         [ +  + ]:         924 :  do iq=1,BSp%nq
     399                 :         924 :    write(funt,'(a,3(f9.6,","),a)')'# q = ',BSp%q(:,iq),' [Reduced coords] '
     400                 :             :  end do
     401                 :             : 
     402                 :             :  ! Write spectra.
     403         [ +  + ]:         132 :  if (.not.PRESENT(dos)) then
     404                 :          28 :    write(funt,'(a)')"# omega [eV]    RE(eps(q=1)) IM(eps(q=1) RE(eps(q=2) ) ... "
     405                 :          28 :    write(frm,*)'(f7.3,',2*BSp%nq,'(1x,f9.4))'
     406         [ +  + ]:       13349 :    do io=1,BSp%nomega
     407                 :       13321 :      omegaev = DBLE(BSp%omega(io))*Ha_eV
     408         [ +  + ]:       93247 :      tmp_eps(1,:) = REAL (eps(io,:))
     409         [ +  + ]:       93247 :      tmp_eps(2,:) = AIMAG(eps(io,:))
     410                 :             :      !where (ABS(tmp_eps) < SMALL) ! this to improve the portability of the automatic tests.
     411                 :             :      !  tmp_eps = zero
     412                 :             :      !end where
     413   [ +  -  +  + ]:       93275 :      write(funt,frm) omegaev,(tmp_eps(:,iq), iq=1,BSp%nq)
     414                 :             :    end do
     415                 :             : 
     416                 :             :  else
     417                 :         104 :    write(funt,'(a)')"# omega [eV]    RE(eps(q=1)) IM(eps(q=1) RE(eps(q=2) ) ... DOS   IDOS"
     418                 :         104 :    step = DBLE(BSp%omega(2) - BSp%omega(1))
     419         [ -  + ]:         104 :    if ( ABS( step - DBLE((BSp%omega(BSp%nomega) - BSp%omega(BSp%nomega-1)))) > tol6 ) then
     420                 :           0 :      ABI_WARNING("Frequency mesh must be linear for using simpson_int")
     421                 :             :    end if
     422                 :         104 :    call simpson_int(Bsp%nomega,step,dos,int_dos)
     423                 :             :    !write(frm,*)'(f7.3,',2*BSp%nq,'es12.4,2es12.4)'
     424                 :         104 :    write(frm,*)'(f7.3,',2*BSp%nq,'(1x,f9.4,1x,f9.4,1x,f9.4))'
     425         [ +  + ]:       69418 :    do io=1,BSp%nomega
     426                 :       69314 :      omegaev = DBLE(BSp%omega(io))*Ha_eV
     427         [ +  + ]:      485198 :      tmp_eps(1,:) = REAL (eps(io,:))
     428         [ +  + ]:      485198 :      tmp_eps(2,:) = AIMAG(eps(io,:))
     429                 :             :      !where (ABS(tmp_eps) < SMALL) ! this to improve the portability of the automatic tests.
     430                 :             :      !  tmp_eps = zero
     431                 :             :      !end where
     432                 :             :      !write(funt,frm) omegaev,(eps(io,iq), iq=1,BSp%nq), dos(io), int_dos(io)
     433   [ +  -  +  + ]:      485302 :      write(funt,frm) omegaev,(tmp_eps(:,iq), iq=1,BSp%nq), dos(io), int_dos(io)
     434                 :             :    end do
     435                 :             :  end if
     436                 :             : 
     437                 :         132 :  close(funt)
     438                 :             : 
     439                 :         132 : end subroutine exc_write_data
     440                 :             : !!***
     441                 :             : 
     442                 :             : !----------------------------------------------------------------------
     443                 :             : 
     444                 :             : !!****f* m_exc_spectra/exc_eps_rpa
     445                 :             : !! NAME
     446                 :             : !!  exc_eps_rpa
     447                 :             : !!
     448                 :             : !! FUNCTION
     449                 :             : !!  Build epsilon within RPA and GW.
     450                 :             : !!
     451                 :             : !! INPUTS
     452                 :             : !! nkbz=Number of points in the BZ
     453                 :             : !! nbnds=Number of bands
     454                 :             : !! lomo_spin(nsppol)
     455                 :             : !! lomo_min=Lowest occupied state
     456                 :             : !! homo=Number of occupied states.
     457                 :             : !! homo_spin(nsppol)
     458                 :             : !! nsppol=Number of independent spin polarizations.
     459                 :             : !! nomega=Number of frequencies
     460                 :             : !! omega(nomega)=Frequency mesh.
     461                 :             : !! ucvol=Unit cell volume.
     462                 :             : !! broad=Broadening used for the DOS.
     463                 :             : !! opt_cvk(nbnds,nbnds,nkbz)=Matrix elements <b k|e^{-iqr}|b" k> for a given q in the full BZ.
     464                 :             : !!
     465                 :             : !! OUTPUT
     466                 :             : !!  eps_rpa(nomega)=RPA spectrum without local-field effects.
     467                 :             : !!  dos(nomega)=The DOS.
     468                 :             : !!
     469                 :             : !! SOURCE
     470                 :             : 
     471                 :          96 : subroutine exc_eps_rpa(nbnds,lomo_spin,lomo_min,homo_spin,Kmesh,Bst,nq,nsppol,opt_cvk,ucvol,broad,nomega,omega,eps_rpa,dos)
     472                 :             : 
     473                 :             : !Arguments ------------------------------------
     474                 :             : !scalars
     475                 :             :  integer,intent(in) :: nbnds,lomo_min,nsppol,nomega,nq
     476                 :             :  real(dp),intent(in) :: ucvol,broad
     477                 :             :  type(kmesh_t),intent(in) :: Kmesh
     478                 :             :  type(ebands_t),intent(in) :: BSt
     479                 :             : !arrays
     480                 :             :  integer,intent(in) :: lomo_spin(nsppol),homo_spin(nsppol)
     481                 :             :  real(dp),intent(out) :: dos(nomega)
     482                 :             :  complex(dp),intent(in) :: omega(nomega)
     483                 :             :  complex(dp),intent(in) :: opt_cvk(lomo_min:nbnds,lomo_min:nbnds,Kmesh%nbz,nsppol,nq)
     484                 :             :  complex(dp),intent(out) :: eps_rpa(nomega,nq)
     485                 :             : 
     486                 :             : !Local variables ------------------------------
     487                 :             : !scalars
     488                 :             :  integer :: iw,ib_v,ib_c,ik_bz,ik_ibz,spin,iq
     489                 :             :  real(dp) :: fact,arg,ediff
     490                 :             :  real(dp) :: linewidth
     491                 :             :  complex(dp) :: ctemp
     492                 :             :  logical :: do_linewidth
     493                 :             : !************************************************************************
     494                 :             : 
     495                 :             :  ! TODO: four_pi comes from the bare Coulomb term hence the
     496                 :             :  ! present implementation is not compatible with the cutoff technique.
     497                 :          96 :  fact=four_pi/(ucvol*Kmesh%nbz)
     498         [ +  + ]:          96 :  if (nsppol==1) fact=two*fact ! two accounts for the occupation factors.
     499                 :             : 
     500   [ +  +  +  +  :      403158 :  eps_rpa=czero; dos=zero
                   +  + ]
     501                 :             : 
     502                 :          96 :  do_linewidth = .FALSE.
     503                 :          96 :  do_linewidth = allocated(BSt%linewidth)
     504                 :             : 
     505                 :             :  !write(std_out,*)nsppol,Kmesh%nbz,lomo_min,homo,nbnds
     506                 :             :  !
     507                 :             :  ! Sum over all QP transitions.
     508         [ +  + ]:         194 :  do spin=1,nsppol
     509         [ +  + ]:        3314 :    do ik_bz=1,Kmesh%nbz
     510                 :        3120 :      ik_ibz = Kmesh%tab(ik_bz)
     511         [ +  + ]:       12466 :      do ib_v=lomo_spin(spin),homo_spin(spin)
     512         [ +  + ]:       42192 :        do ib_c=homo_spin(spin)+1,nbnds
     513                 :             :          !
     514                 :             :          ! TODO here energies are always assumed to be real.
     515                 :       29824 :          ediff = BSt%eig(ib_c,ik_ibz,spin) - BSt%eig(ib_v,ik_ibz,spin)
     516                 :             : 
     517         [ +  + ]:       39072 :          if(do_linewidth) then
     518                 :        3840 :            linewidth = BSt%linewidth(1,ib_c,ik_ibz,spin) + BSt%linewidth(1,ib_v,ik_ibz,spin)
     519         [ +  + ]:       26880 :            do iq=1,nq
     520                 :       23040 :              ctemp = opt_cvk(ib_c,ib_v,ik_bz,spin,iq)
     521         [ +  + ]:    23089920 :              do iw=1,nomega
     522                 :             :                eps_rpa(iw,iq) = eps_rpa(iw,iq)  + ctemp * CONJG(ctemp) *&
     523                 :    23086080 :                  (one/(ediff-j_dpc*linewidth-omega(iw)) + one/(ediff+j_dpc*linewidth+omega(iw)))
     524                 :             :              end do
     525                 :             :            end do
     526                 :             :            ! The JDOS at q=0
     527                 :             :            !if (ediff*Ha_eV < 0.3) then
     528                 :             :            !  write(std_out,*)"Small transition ",ik_ibz,ib_v,ib_c
     529                 :             :            !end if
     530                 :             : 
     531         [ +  + ]:     3847680 :            do iw=1,nomega
     532                 :     3843840 :              arg = DBLE(omega(iw)) - ediff
     533                 :     3847680 :              dos(iw) = dos(iw) + gaussian(arg, linewidth)
     534                 :             :            end do
     535                 :             :          else
     536         [ +  + ]:      181888 :            do iq=1,nq
     537                 :      155904 :              ctemp = opt_cvk(ib_c,ib_v,ik_bz,spin,iq)
     538         [ +  + ]:    40669696 :              do iw=1,nomega
     539                 :             :                eps_rpa(iw,iq) = eps_rpa(iw,iq)  + ctemp * CONJG(ctemp) *&
     540                 :    40643712 :                (one/(ediff-omega(iw)) + one/(ediff+omega(iw)))
     541                 :             :              end do
     542                 :             :            end do
     543                 :             :            !
     544                 :             :            ! The JDOS at q=0
     545                 :             :            !if (ediff*Ha_eV < 0.3) then
     546                 :             :            !  write(std_out,*)"Small transition ",ik_ibz,ib_v,ib_c
     547                 :             :            !end if
     548                 :             : 
     549         [ +  + ]:     6773952 :            do iw=1,nomega
     550                 :     6747968 :              arg = DBLE(omega(iw)) - ediff
     551                 :     6773952 :              dos(iw) = dos(iw) + gaussian(arg, broad)
     552                 :             :            end do
     553                 :             :          end if
     554                 :             :          !
     555                 :             :        end do !ib_c
     556                 :             :      end do !ib_v
     557                 :             :    end do !ik_bz
     558                 :             :  end do !spin
     559                 :             : 
     560         [ +  + ]:       57594 :  dos = dos/Kmesh%nbz
     561   [ +  +  +  + ]:      345660 :  eps_rpa = cone + fact*eps_rpa
     562                 :             : 
     563                 :          96 : end subroutine exc_eps_rpa
     564                 :             : !!***
     565                 :             : 
     566                 :             : !----------------------------------------------------------------------
     567                 :             : 
     568                 :             : !!****f* m_exc_spectra/exc_eps_resonant
     569                 :             : !! NAME
     570                 :             : !!  exc_eps_resonant
     571                 :             : !!
     572                 :             : !! FUNCTION
     573                 :             : !!  This routine builds the macroscopic dielectric function with excitonic effects.
     574                 :             : !!
     575                 :             : !! INPUTS
     576                 :             : !! Bsp
     577                 :             : !! lomo_min,max_band
     578                 :             : !! nkbz=Number of points in the BZ
     579                 :             : !! nsppol=Number of independent polarizations.
     580                 :             : !! nomega=Number of frequencies
     581                 :             : !! omega(nomega)=frequency mesh (complex shift is already included)
     582                 :             : !! ucvol=Volume of the unit cell.
     583                 :             : !! opt_cvk(lomo_min:max_band,mib:max_band,nkbz,nsppol,Bsp%nq)=Matrix elements <b k|e^{-iqr}|b" k> for a given q in the full BZ.
     584                 :             : !!
     585                 :             : !! OUTPUT
     586                 :             : !!  eps_exc(nomega,Bsp%nq)=Macroscopic dielectric function with excitonic effects.
     587                 :             : !!  dos_exc(nomega)=The DOS of the excitonic Hamiltonian
     588                 :             : !!
     589                 :             : !! SOURCE
     590                 :             : 
     591                 :          15 : subroutine exc_eps_resonant(Bsp,filbseig,ost_fname,lomo_min,max_band,nkbz,nsppol,opt_cvk,&
     592                 :          15 :                             ucvol,nomega,omega,eps_exc,dos_exc,elph_lifetime)
     593                 :             : 
     594                 :             : !Arguments ------------------------------------
     595                 :             : !scalars
     596                 :             :  integer,intent(in) :: lomo_min,max_band,nkbz,nomega,nsppol
     597                 :             :  real(dp),intent(in) :: ucvol
     598                 :             :  type(excparam),intent(in) :: BSp
     599                 :             :  character(len=fnlen),intent(in) :: filbseig,ost_fname
     600                 :             :  logical,optional,intent(in) :: elph_lifetime
     601                 :             : !arrays
     602                 :             :  real(dp),intent(out) :: dos_exc(nomega)
     603                 :             :  complex(dp),intent(in) :: opt_cvk(lomo_min:max_band,lomo_min:max_band,nkbz,nsppol,BSp%nq),omega(nomega)
     604                 :             :  complex(dp),intent(out) :: eps_exc(nomega,BSp%nq)
     605                 :             : 
     606                 :             : !Local variables ------------------------------
     607                 :             : !scalars
     608                 :             :  integer :: ll,it,iw,ib_v,ib_c,ik_bz,neig_read,eig_unt,exc_size,iq !fform,
     609                 :             :  integer :: spin,spad,hsize_read,nstates,ost_unt
     610                 :             :  logical :: do_ep_lifetime, file_do_lifetime
     611                 :             :  real(dp) :: fact,arg
     612                 :             :  complex(dp) :: dotprod
     613                 :             :  character(len=500) :: msg,frm,errmsg
     614                 :             : !arrays
     615                 :          15 :  real(dp),allocatable :: exc_ene(:)
     616                 :          15 :  complex(dp) :: ctemp(BSp%nq),dtemp(BSp%nq)
     617                 :          15 :  complex(dp),allocatable :: ostrength(:,:),exc_ene_cplx(:),exc_state(:),exc_state2(:)
     618                 :             : !************************************************************************
     619                 :             : 
     620                 :          15 :  call wrtout(std_out," Calculating excitonic epsilon with antiresonant")
     621                 :             : 
     622         [ +  + ]:          15 :  if (nsppol==2) then
     623                 :           1 :    ABI_WARNING("nsppol==2 still under development")
     624                 :             :  end if
     625                 :             : 
     626         [ +  + ]:          31 :  exc_size = SUM(BSp%nreh)
     627                 :          15 :  nstates  = BSp%nstates
     628                 :             : 
     629                 :          15 :  do_ep_lifetime = .FALSE.
     630         [ +  - ]:          15 :  if (PRESENT(elph_lifetime)) do_ep_lifetime = elph_lifetime
     631                 :             : 
     632   [ +  +  +  -  :          31 :  if (ANY(Bsp%nreh/=Bsp%nreh(1))) then
                   -  + ]
     633                 :           0 :    write(msg,'(a,2(i0,1x))')"BSE does not support different number of transitions for the two spin channels. nreh: ",Bsp%nreh
     634                 :           0 :    ABI_WARNING(msg)
     635                 :             :  end if
     636                 :             :  !
     637                 :             :  ! TODO:
     638                 :             :  ! four_pi comes from the bare Coulomb term hence the
     639                 :             :  ! present implementation is not compatible with the cutoff technique.
     640         [ +  + ]:          15 :  fact=four_pi/(ucvol*nkbz); if (nsppol==1) fact=two*fact ! two to account for the occupation numbers.
     641                 :             : 
     642         [ +  - ]:          15 :  call wrtout(std_out," Reading excitonic eigenstates from file: "//TRIM(filbseig))
     643         [ -  + ]:          15 :  if (open_file(filbseig,msg,newunit=eig_unt,form="unformatted",status="old",action="read") /= 0) then
     644                 :           0 :    ABI_ERROR(msg)
     645                 :             :  end if
     646                 :             : 
     647         [ +  - ]:          15 :  read(eig_unt, err=10, iomsg=errmsg) file_do_lifetime
     648                 :             : 
     649   [ +  +  -  + ]:          15 :  if(do_ep_lifetime .and. .not. file_do_lifetime) then
     650                 :           0 :   ABI_ERROR("Cannot do lifetime as the data is not present in the file !")
     651                 :             :  end if
     652                 :             : 
     653         [ +  - ]:          15 :  read(eig_unt, err=10, iomsg=errmsg) hsize_read,neig_read
     654                 :             : 
     655         [ -  + ]:          15 :  if (hsize_read /= exc_size) then
     656                 :           0 :    write(msg,'(2(a,i0))')" Wrong size of the Hamiltonian: read: ",hsize_read," expected= ",exc_size
     657                 :           0 :    ABI_ERROR(msg)
     658                 :             :  end if
     659                 :             : 
     660         [ -  + ]:          15 :  if (neig_read /= nstates) then
     661                 :           0 :    write(msg,'(2(a,i0))')" Wrong number of eigenstates: read: ",neig_read," expected= ",nstates
     662                 :           0 :    ABI_ERROR(msg)
     663                 :             :  end if
     664                 :             :  !
     665                 :             :  ! Read eigenvalues, ignore possibly small imaginary part.
     666   [ -  +  +  -  :          45 :  ABI_MALLOC(exc_ene_cplx,(neig_read))
          +  -  +  -  -  
                +  -  + ]
     667         [ +  - ]:          15 :  read(eig_unt, err=10, iomsg=errmsg) exc_ene_cplx
     668                 :             : 
     669   [ -  +  +  -  :          45 :  ABI_MALLOC(exc_ene,(neig_read))
          +  -  +  -  -  
                +  -  + ]
     670   [ +  -  -  +  :        2258 :  exc_ene = DBLE(exc_ene_cplx)
             -  -  +  + ]
     671                 :             :  !ABI_FREE(exc_ene_cplx)
     672                 :             :  !
     673                 :             :  ! Calculate oscillator strength.
     674   [ -  +  +  -  :          45 :  ABI_MALLOC(exc_state,(exc_size))
          +  -  +  -  -  
                +  -  + ]
     675   [ -  +  +  -  :          60 :  ABI_MALLOC(ostrength,(neig_read,BSp%nq))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     676                 :             : 
     677         [ +  + ]:          15 :  if (do_ep_lifetime) then
     678   [ -  +  +  -  :          20 :    ABI_MALLOC(exc_state2,(exc_size))
             -  +  -  + ]
     679         [ +  + ]:         970 :    do ll=1,neig_read ! Loop over excitonic eigenstates reported on file.
     680         [ +  - ]:         960 :      read(eig_unt, err=10, iomsg=errmsg) exc_state(:) ! Righteigenvector
     681         [ +  - ]:         960 :      read(eig_unt, err=10, iomsg=errmsg) exc_state2(:) ! Lefteigenvector
     682                 :             : 
     683                 :             :      ! Here assuming that eigenvectors are such as Xl_i' Xr_j = delta_ij
     684                 :             :      ! Otherwise, I need to invert the overlap matrix !
     685                 :             : 
     686                 :             :      ! Rescale the vectors so that they are "normalized" with respect to the other one !
     687                 :         960 :      dotprod = xdotc(exc_size,exc_state2(:),1,exc_state(:),1)
     688         [ +  + ]:       93120 :      exc_state2(:) = exc_state2(:)/CONJG(dotprod)
     689                 :             : 
     690         [ +  + ]:        6720 :      ctemp(:) = czero
     691         [ +  + ]:        6720 :      dtemp(:) = czero
     692         [ +  + ]:        1920 :      do spin=1,nsppol
     693                 :         960 :        spad=(spin-1)*BSp%nreh(1) ! Loop over spin channels.
     694         [ +  + ]:       94080 :        do it=1,BSp%nreh(spin)    ! Loop over resonant transition t = (k,v,c,s)
     695                 :       92160 :          ik_bz = Bsp%Trans(it,spin)%k
     696                 :       92160 :          ib_v  = Bsp%Trans(it,spin)%v
     697                 :       92160 :          ib_c  = Bsp%Trans(it,spin)%c
     698         [ +  + ]:      646080 :          do iq=1,BSp%nq
     699                 :      552960 :            ctemp(iq) = ctemp(iq) + CONJG(opt_cvk(ib_c,ib_v,ik_bz,spin,iq)) * exc_state(it+spad)
     700                 :      645120 :            dtemp(iq) = dtemp(iq) + CONJG(opt_cvk(ib_c,ib_v,ik_bz,spin,iq)) * exc_state2(it+spad)
     701                 :             :          end do
     702                 :             :        end do ! it
     703                 :             :      end do
     704         [ +  + ]:        6730 :      ostrength(ll,:) = ctemp(:)*CONJG(dtemp(:))
     705                 :             :    end do ! ll
     706         [ -  + ]:          10 :    ABI_FREE(exc_state2)
     707                 :             :  else
     708         [ +  + ]:        1273 :    do ll=1,neig_read ! Loop over excitonic eigenstates reported on file.
     709         [ +  - ]:        1268 :      read(eig_unt, err=10, iomsg=errmsg) exc_state(:)
     710   [ -  +  -  - ]:        1268 :      if(file_do_lifetime) read(eig_unt, err=10, iomsg=errmsg)
     711                 :             : 
     712         [ +  + ]:        8876 :      ctemp(:) = czero
     713         [ +  + ]:        3304 :      do spin=1,nsppol
     714                 :        2036 :        spad=(spin-1)*BSp%nreh(1) ! Loop over spin channels.
     715         [ +  + ]:      757480 :        do it=1,BSp%nreh(spin)    ! Loop over resonant transition t = (k,v,c,s)
     716                 :      754176 :          ik_bz = Bsp%Trans(it,spin)%k
     717                 :      754176 :          ib_v  = Bsp%Trans(it,spin)%v
     718                 :      754176 :          ib_c  = Bsp%Trans(it,spin)%c
     719         [ +  + ]:     5281268 :          do iq=1,BSp%nq
     720                 :     5279232 :            ctemp(iq) = ctemp(iq) + CONJG(opt_cvk(ib_c,ib_v,ik_bz,spin,iq)) * exc_state(it+spad)
     721                 :             :          end do
     722                 :             :        end do ! it
     723                 :             :      end do
     724         [ +  + ]:        8881 :      ostrength(ll,:) = ctemp(:)*CONJG(ctemp(:))
     725                 :             :    end do ! ll
     726                 :             :  end if
     727                 :             : 
     728                 :             : 
     729         [ +  - ]:          15 :  close(eig_unt, err=10, iomsg=errmsg)
     730         [ -  + ]:          15 :  ABI_FREE(exc_state)
     731                 :             : 
     732         [ +  + ]:          15 :  if(do_ep_lifetime) then
     733   [ +  +  +  + ]:       60130 :    eps_exc = one
     734         [ +  + ]:         970 :    do ll=1,neig_read ! Sum over all excitonic eigenstates read from file.
     735         [ +  + ]:        6730 :      do iq=1,BSp%nq
     736         [ +  + ]:     5772480 :         do iw=1,nomega
     737                 :             :           eps_exc(iw,iq) = eps_exc(iw,iq) +  &
     738                 :     5771520 :             fact * ostrength(ll,iq) * (one/(exc_ene_cplx(ll) - omega(iw)) - one/(-DCONJG(exc_ene_cplx(ll)) - omega(iw)))
     739                 :             :         end do
     740                 :             :      end do !ll
     741                 :             :    end do !iw
     742                 :             :  else
     743   [ +  +  +  + ]:       24713 :    eps_exc = one
     744         [ +  + ]:        1273 :    do ll=1,neig_read ! Sum over all excitonic eigenstates read from file.
     745         [ +  + ]:        8881 :      do iq=1,BSp%nq
     746         [ +  + ]:     1458164 :         do iw=1,nomega
     747                 :             :           eps_exc(iw,iq) = eps_exc(iw,iq) +  &
     748                 :     1456896 :             fact * ostrength(ll,iq) * (one/(exc_ene(ll) - omega(iw)) - one/(-exc_ene(ll) - omega(iw)))
     749                 :             :         end do
     750                 :             :      end do !ll
     751                 :             :    end do !iw
     752                 :             :  end if
     753                 :             : 
     754                 :             :  ! The excitonic DOS.
     755         [ +  + ]:       14138 :  dos_exc=zero
     756         [ +  + ]:        2243 :  do ll=1,neig_read ! Sum over the calculate excitonic eigenstates.
     757         [ +  + ]:     1204751 :    do iw=1,nomega
     758                 :     1202508 :      arg = ( DBLE(omega(iw)) - exc_ene(ll))
     759         [ +  + ]:     1204736 :      if(do_ep_lifetime) then
     760                 :      960960 :        dos_exc(iw) = dos_exc(iw) + gaussian(arg, AIMAG(exc_ene_cplx(ll)))
     761                 :             :      else
     762                 :      241548 :        dos_exc(iw) = dos_exc(iw) + gaussian(arg, Bsp%broad)
     763                 :             :      end if
     764                 :             :    end do
     765                 :             :  end do
     766                 :             : 
     767                 :             :  ! Write oscillator strengths to file.
     768         [ -  + ]:          15 :  if (open_file(ost_fname,msg,newunit=ost_unt,form="formatted",action="write") /= 0) then
     769                 :           0 :    ABI_ERROR(msg)
     770                 :             :  end if
     771                 :             : 
     772                 :          15 :  write(ost_unt,'("# Oscillator strengths of the excitonic states for the different q-polarizations.")')
     773                 :             : 
     774                 :             :  ! Write the list of q-points.
     775                 :          15 :  write(ost_unt,*)"# List of q-points for the optical limit"
     776         [ +  + ]:         105 :  do iq=1,BSp%nq
     777                 :         105 :    write(ost_unt,'(a,3(f9.6,","),a)')'# q = ',BSp%q(:,iq),' [Reduced coords] '
     778                 :             :  end do
     779                 :             : 
     780                 :          15 :  write(ost_unt,*)"# E_lambda [eV]     ostrength(q=1) ostrength(q=2) .... "
     781                 :          15 :  write(frm,*)'(f8.4,',BSp%nq,'es12.4)'
     782         [ +  + ]:        2243 :  do ll=1,neig_read
     783                 :        2243 :    write(ost_unt,frm)exc_ene(ll)*Ha_eV,(ostrength(ll,iq), iq=1,BSp%nq)
     784                 :             :  end do
     785                 :             : 
     786                 :          15 :  close(ost_unt)
     787                 :             : 
     788         [ -  + ]:          15 :  ABI_FREE(ostrength)
     789         [ -  + ]:          15 :  ABI_FREE(exc_ene)
     790         [ -  + ]:          15 :  ABI_FREE(exc_ene_cplx)
     791                 :             : 
     792                 :             :  !call exc_amplitude(Bsp,filbseig,1,(/(ll,ll=1,10)/),"TEST_AMPLITUDE")
     793                 :             :  !call exc_amplitude(Bsp,filbseig,1,(/30/),"TEST_AMPLITUDE")
     794                 :          15 :  return
     795                 :             : 
     796                 :             :  ! Handler IO-error
     797                 :             : 10 continue
     798                 :           0 :  ABI_ERROR(errmsg)
     799                 :             : 
     800   [ +  -  -  -  :          15 : end subroutine exc_eps_resonant
          -  -  -  -  -  
                -  -  - ]
     801                 :             : !!***
     802                 :             : 
     803                 :             : !----------------------------------------------------------------------
     804                 :             : 
     805                 :             : !!****f* m_exc_spectra/exc_eps_coupling
     806                 :             : !! NAME
     807                 :             : !!  exc_eps_coupling
     808                 :             : !!
     809                 :             : !! FUNCTION
     810                 :             : !!  Make epsilon EXCITONIC with full COUPLING.
     811                 :             : !!
     812                 :             : !! INPUTS
     813                 :             : !! Bsp
     814                 :             : !! nkbz=Number of points in the BZ
     815                 :             : !! lomo_min,max_band
     816                 :             : !! nomega=Number of frequencies
     817                 :             : !! omega(nomega)=frequency mesh.
     818                 :             : !! nsppol=Number of independent spin polarizations.
     819                 :             : !! ucvol=Unit cell volume.
     820                 :             : !! BS_files<excfiles>File names used in the Bethe-Salpeter code.
     821                 :             : !! opt_cvk(lomo_min:max_band,lomo_min:max_band,nkbz,nsppol)=Matrix elements <b k|e^{-iqr}|b" k> for a given q in the full BZ.
     822                 :             : !!
     823                 :             : !! OUTPUT
     824                 :             : !!  eps_exc(nomega)=Macroscopic dielectric function with excitonic effects calculated including the COUPLING.
     825                 :             : !!  dos_exc(nomega)=The DOS of the excitonic Hamiltonian
     826                 :             : !!
     827                 :             : !! SOURCE
     828                 :             : 
     829                 :           1 : subroutine exc_eps_coupling(Bsp,BS_files,lomo_min,max_band,nkbz,nsppol,opt_cvk,ucvol,nomega,omega,eps_exc,dos_exc)
     830                 :             : 
     831                 :             : !Arguments ------------------------------------
     832                 :             : !scalars
     833                 :             :  integer,intent(in) :: lomo_min,max_band,nkbz,nomega,nsppol
     834                 :             :  real(dp),intent(in) :: ucvol
     835                 :             :  type(excfiles),intent(in) :: BS_files
     836                 :             :  type(excparam),intent(in) :: BSp
     837                 :             : !arrays
     838                 :             :  real(dp),intent(out) :: dos_exc(nomega)
     839                 :             :  complex(dp),intent(in) :: opt_cvk(lomo_min:max_band,lomo_min:max_band,nkbz,nsppol,BSp%nq),omega(nomega)
     840                 :             :  complex(dp),intent(out) :: eps_exc(nomega,BSp%nq)
     841                 :             : 
     842                 :             : !Local variables ------------------------------
     843                 :             : !scalars
     844                 :             :  integer :: mi,it,ii,ib_v,ib_c,ik_bz,exc_size_read,nstates_read,eig_unt !,fform
     845                 :             :  integer :: exc_size,iq,spin,tr_idx,tar_idx,nstates,iw,ll,ierr
     846                 :             :  real(dp) :: fact,arg
     847                 :             :  complex(dp) :: eps,fam,famp
     848                 :             :  character(len=500) :: msg,errmsg
     849                 :             :  character(len=fnlen) :: filbseig
     850                 :             :  logical :: do_lifetime
     851                 :             : !arrays
     852                 :           1 :  complex(dp),allocatable :: Ami(:),exc_ene(:),Sm1mi(:)
     853                 :           1 :  complex(dp),allocatable :: msfap(:,:),fa(:,:),fap(:,:)
     854                 :             : !************************************************************************
     855                 :             : 
     856                 :           1 :  call wrtout(std_out," Calculating absorption strength with full coupling")
     857                 :             : 
     858         [ -  + ]:           1 :  if (nsppol==2) then
     859                 :           0 :    ABI_WARNING("nsppol==2 is still under development")
     860                 :             :  end if
     861                 :             : 
     862                 :             :  ! Rank of the entire excitonic Hamiltonian including the coupling block.
     863   [ +  +  -  +  :           2 :  exc_size = 2*SUM(BSp%nreh); if (nsppol==2) exc_size = 2*(SUM(BSp%nreh) + BSp%nreh(2))
                   -  - ]
     864                 :           1 :  nstates  = BSp%nstates
     865                 :             : 
     866                 :             :  ! TODO: four_pi comes from the bare Coulomb term hence the
     867                 :             :  ! present implementation is not compatible with the cutoff technique.
     868                 :             :  ! factor two is due to the occupation factors.
     869         [ +  - ]:           1 :  fact=four_pi/(ucvol*nkbz); if (nsppol==1) fact=two*fact
     870                 :             : 
     871         [ -  + ]:           1 :  if (BS_files%in_eig /= BSE_NOFILE) then
     872                 :           0 :    filbseig = BS_files%in_eig
     873                 :             :  else
     874                 :           1 :    filbseig = BS_files%out_eig
     875                 :             :  end if
     876                 :             : 
     877         [ +  - ]:           1 :  call wrtout(std_out," Reading excitonic eigenstates from file: "//trim(filbseig))
     878         [ -  + ]:           1 :  if (open_file(filbseig,msg,newunit=eig_unt,form="unformatted", status="old", action="read") /= 0) then
     879                 :           0 :    ABI_ERROR(msg)
     880                 :             :  end if
     881                 :             : 
     882         [ +  - ]:           1 :  read(eig_unt, err=10, iomsg=errmsg) do_lifetime
     883                 :             : 
     884         [ -  + ]:           1 :  if (do_lifetime) then
     885                 :           0 :    ABI_CHECK(.not. do_lifetime, "Finite lifetime with coupling is not supported yet !")
     886                 :             :  end if
     887                 :             : 
     888         [ +  - ]:           1 :  read(eig_unt, err=10, iomsg=errmsg) exc_size_read, nstates_read
     889         [ -  + ]:           1 :  ABI_CHECK(exc_size_read==exc_size,"wrong file")
     890         [ -  + ]:           1 :  ABI_CHECK(nstates_read==nstates,"Partial diago not supported yet")
     891                 :             :  !
     892                 :             :  ! Read eigenvalues
     893   [ -  +  +  -  :           3 :  ABI_MALLOC(exc_ene,(nstates))
          +  -  +  -  -  
                +  -  + ]
     894         [ +  - ]:           1 :  read(eig_unt, err=10, iomsg=errmsg) exc_ene(:)
     895                 :             : 
     896   [ -  +  +  -  :           4 :  ABI_MALLOC(fa,(nstates,BSp%nq))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     897   [ -  +  +  -  :           3 :  ABI_MALLOC(fap,(nstates,BSp%nq))
          -  +  +  -  -  
                +  -  + ]
     898   [ -  +  +  -  :           3 :  ABI_MALLOC_OR_DIE(Ami,(exc_size), ierr)
          +  -  +  -  +  
             -  -  +  -  
                      + ]
     899                 :             : 
     900         [ +  + ]:         769 :  do mi=1,nstates ! Loop on excitonic eigenvalues mi
     901         [ +  - ]:         768 :    read(eig_unt, err=10, iomsg=errmsg) Ami(:)
     902                 :             : 
     903         [ +  + ]:        5377 :    do iq=1,BSp%nq
     904                 :             :      fam  = czero
     905                 :             :      famp = czero
     906         [ +  + ]:        9216 :      do spin=1,nsppol
     907         [ +  + ]:     1778688 :        do it=1,BSp%nreh(spin) ! Loop over transition t = (k,v,c)
     908                 :     1769472 :          ik_bz = Bsp%Trans(it,spin)%k
     909                 :     1769472 :          ib_v  = Bsp%Trans(it,spin)%v
     910                 :     1769472 :          ib_c  = Bsp%Trans(it,spin)%c
     911                 :     1769472 :          tr_idx  = it + (spin-1)*Bsp%nreh(1)
     912         [ +  - ]:     1769472 :          if (nsppol==1) then
     913                 :     1769472 :            tar_idx = it + Bsp%nreh(1)
     914                 :             :          else
     915   [ #  #  #  # ]:           0 :            if (spin==1) tar_idx = it + SUM(Bsp%nreh)
     916         [ #  # ]:           0 :            if (spin==2) tar_idx = it + 2*Bsp%nreh(1)+Bsp%nreh(2)
     917                 :             :          end if
     918                 :             : 
     919                 :             :          fam = fam + CONJG(opt_cvk(ib_c,ib_v,ik_bz,spin,iq)) * Ami(tr_idx) &
     920                 :     1769472 :                    + CONJG(opt_cvk(ib_v,ib_c,ik_bz,spin,iq)) * Ami(tar_idx)
     921                 :             : 
     922                 :             :          famp = famp - opt_cvk(ib_c,ib_v,ik_bz,spin,iq) * CONJG(Ami(tr_idx)) &
     923                 :     1774080 :                      + opt_cvk(ib_v,ib_c,ik_bz,spin,iq) * CONJG(Ami(tar_idx))
     924                 :             :        end do
     925                 :             :      end do
     926                 :             :      ! Save results.
     927                 :        4608 :      fa (mi,iq) = fam
     928                 :        5376 :      fap(mi,iq) = famp
     929                 :             :    end do
     930                 :             :  end do ! mi
     931                 :             : 
     932         [ -  + ]:           1 :  ABI_FREE(Ami)
     933                 :             : 
     934                 :             :  ! Read O{-1} and sum over the eigenstates.
     935   [ -  +  +  -  :           3 :  ABI_MALLOC(msfap,(nstates,BSp%nq))
          -  +  +  -  -  
                +  -  + ]
     936   [ -  +  +  -  :           2 :  ABI_MALLOC(Sm1mi,(nstates))
             -  +  -  + ]
     937                 :             : 
     938         [ +  + ]:         769 :  do mi=1,nstates
     939         [ +  - ]:         768 :    read(eig_unt, err=10, iomsg=errmsg) Sm1mi
     940         [ +  + ]:      590592 :    Sm1mi = DCONJG(Sm1mi) ! This gives the row since O^{-1} is Hermitian.
     941         [ +  + ]:        5377 :    do iq=1,BSp%nq
     942                 :        5376 :      msfap(mi,iq) = xdotu(exc_size,Sm1mi,1,fap(:,iq),1)
     943                 :             :    end do
     944                 :             :  end do
     945                 :             : 
     946         [ -  + ]:           1 :  ABI_FREE(Sm1mi)
     947                 :             : 
     948         [ +  - ]:           1 :  close(eig_unt, err=10, iomsg=errmsg)
     949                 :             : 
     950                 :             :  ! === Calculate excitonic epsilon with coupling ===
     951         [ +  + ]:           7 :  do iq=1,BSp%nq
     952                 :             :    !
     953         [ +  + ]:         613 :    do ii=1,nomega
     954                 :             :      eps = czero
     955         [ +  + ]:      466014 :      do mi=1,nstates ! sum over all exciton eigenstates
     956                 :      466014 :        eps = eps - fa(mi,iq) * msfap(mi,iq) / (exc_ene(mi) - omega(ii))
     957                 :             :      end do
     958                 :         612 :      eps_exc(ii,iq) = one + fact * eps
     959                 :             :    end do
     960                 :             :  end do
     961                 :             : 
     962         [ -  + ]:           1 :  ABI_FREE(fa)
     963         [ -  + ]:           1 :  ABI_FREE(msfap)
     964         [ -  + ]:           1 :  ABI_FREE(fap)
     965                 :             : 
     966                 :             :  ! The excitonic DOS.
     967         [ +  + ]:         102 :  dos_exc=zero
     968         [ +  + ]:         769 :  do ll=1,nstates ! Sum over the calculate excitonic eigenstates.
     969         [ +  + ]:       78337 :    do iw=1,nomega
     970                 :       77568 :      arg = DBLE(omega(iw) - exc_ene(ll))
     971                 :       78336 :      dos_exc(iw) = dos_exc(iw) + gaussian(arg, Bsp%broad)
     972                 :             :    end do
     973                 :             :  end do
     974                 :             : 
     975         [ -  + ]:           1 :  ABI_FREE(exc_ene)
     976                 :             : 
     977                 :             :  return
     978                 :             : 
     979                 :             : 10 continue
     980                 :           0 :  ABI_ERROR(errmsg)
     981                 :             : 
     982   [ #  #  #  #  :           0 : end subroutine exc_eps_coupling
          #  #  #  #  #  
                #  #  # ]
     983                 :             : !!***
     984                 :             : 
     985                 :             : !----------------------------------------------------------------------
     986                 :             : 
     987                 :             : !!****f* m_exc_spectra/exc_write_tensor
     988                 :             : !! NAME
     989                 :             : !!  exc_write_tensor
     990                 :             : !!
     991                 :             : !! FUNCTION
     992                 :             : !!  This routine drives the writing of complex dielectric tensor
     993                 :             : !!
     994                 :             : !! INPUTS
     995                 :             : !! BSp<excparam>=Bethe-Salpeter Parameters.
     996                 :             : !! what= "EXC_TSR_CART" or "EXC_TSR_RED"
     997                 :             : !!       "RPA_NLF_TSR_CART" or "RPA_NLF_TSR_RED"
     998                 :             : !!       "GW_NLF_TSR_CART" or "GW_NLF_TSR_RED"
     999                 :             : !!
    1000                 :             : !! OUTPUT
    1001                 :             : !!  Only writing.
    1002                 :             : !!
    1003                 :             : !! SIDE EFFECTS
    1004                 :             : !!  tensor(BSp%nomega,6) = Complex dielectric tensor to be written
    1005                 :             : !!
    1006                 :             : !! SOURCE
    1007                 :             : 
    1008                 :         168 : subroutine exc_write_tensor(BSp,BS_files,what,tensor)
    1009                 :             : 
    1010                 :             : !Arguments ------------------------------------
    1011                 :             : !scalars
    1012                 :             :  character(len=*),intent(in) :: what
    1013                 :             :  type(excparam),intent(in) :: BSp
    1014                 :             :  type(excfiles),intent(in) :: BS_files
    1015                 :             : !arrays
    1016                 :             :  complex(dp),intent(in) :: tensor(BSp%nomega,6)
    1017                 :             : 
    1018                 :             : !Local variables ------------------------------
    1019                 :             : !scalars
    1020                 :             :  integer :: io,iq,funt
    1021                 :             :  real(dp) :: omegaev
    1022                 :             : !arrays
    1023                 :             :  character(len=500) :: lf_type,block_type,wgg_type,frm,str_type, msg
    1024                 :             :  character(len=fnlen) :: fname
    1025                 :             : !************************************************************************
    1026                 :             : 
    1027         [ +  - ]:         168 :  fname = strcat(BS_files%out_basename,'_',toupper(what))
    1028         [ -  + ]:         168 :  if (open_file(fname,msg,newunit=funt,form="formatted", action="write") /= 0) then
    1029                 :           0 :    ABI_ERROR(msg)
    1030                 :             :  end if
    1031                 :             : 
    1032                 :         364 :  select case (toupper(what))
    1033                 :             :  case ("EXC_TSR_CART")
    1034                 :          28 :    write(funt,'("# Complex dielectric tensor (cart. coord.) obtained with the BS equation.")')
    1035                 :             : 
    1036                 :          28 :    lf_type = 'WITHOUT LOCAL FIELD EFFECTS'
    1037         [ +  - ]:          28 :    if (BSp%exchange_term>0) lf_type='LOCAL FIELD EFFECTS INCLUDED'
    1038                 :          28 :    call bsp%calctype2str(str_type)
    1039                 :          28 :    write(funt,'("# ",a,"     " ,a)') TRIM(str_type), TRIM(lf_type)
    1040                 :             : 
    1041                 :          28 :    block_type = 'RESONANT-ONLY calculation'
    1042         [ -  + ]:          28 :    if (BSp%use_coupling>0) block_type = 'RESONANT+COUPLING calculation'
    1043                 :          28 :    write(funt,'("# ",a)') TRIM(block_type)
    1044                 :             : 
    1045         [ +  - ]:          28 :    if (BSp%use_coulomb_term) then
    1046                 :          28 :      wgg_type = "Coulomb term constructed with full W(G1,G2)"
    1047         [ +  + ]:          28 :      if ( BSp%use_diagonal_Wgg ) wgg_type = "Coulomb term constructed with diagonal approximation W(G1,G1)"
    1048                 :          28 :      write(funt,'("# ",a)') TRIM(wgg_type)
    1049                 :             :    end if
    1050                 :             : 
    1051                 :          28 :    write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]'
    1052                 :             : 
    1053                 :             :  case ("EXC_TSR_RED")
    1054                 :          28 :    write(funt,'("# Complex dielectric tensor (red. coord.) obtained with the BS equation.")')
    1055                 :             : 
    1056                 :          28 :    lf_type = 'WITHOUT LOCAL FIELD EFFECTS'
    1057         [ +  - ]:          28 :    if (BSp%exchange_term>0) lf_type='LOCAL FIELD EFFECTS INCLUDED'
    1058                 :          28 :    call bsp%calctype2str(str_type)
    1059                 :          28 :    write(funt,'("# ",a,"     " ,a)') TRIM(str_type), TRIM(lf_type)
    1060                 :             : 
    1061                 :          28 :    block_type = 'RESONANT-ONLY calculation'
    1062         [ -  + ]:          28 :    if (BSp%use_coupling>0) block_type = 'RESONANT+COUPLING calculation'
    1063                 :          28 :    write(funt,'("# ",a)') TRIM(block_type)
    1064                 :             : 
    1065         [ +  - ]:          28 :    if (BSp%use_coulomb_term) then
    1066                 :          28 :      wgg_type = "Coulomb term constructed with full W(G1,G2)"
    1067         [ +  + ]:          28 :      if ( BSp%use_diagonal_Wgg ) wgg_type = "Coulomb term constructed with diagonal approximation W(G1,G1)"
    1068                 :          28 :      write(funt,'("# ",a)') TRIM(wgg_type)
    1069                 :             :    end if
    1070                 :             : 
    1071                 :          28 :    write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]'
    1072                 :             : 
    1073                 :             :  case ("RPA_NLF_TSR_CART")
    1074                 :          28 :    write(funt,'("# RPA complex dielectric tensor (cart. coord.) without local fields")')
    1075                 :             : 
    1076                 :             :  case ("RPA_NLF_TSR_RED")
    1077                 :          28 :    write(funt,'("# RPA complex dielectric tensor (red. coord.) without local fields")')
    1078                 :             : 
    1079                 :             :  case ("GW_NLF_TSR_CART")
    1080                 :          28 :    write(funt,'("# GW complex dielectric tensor (cart. coord.) without local field effects ")')
    1081                 :          28 :    write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]'
    1082                 :             : 
    1083                 :             :  case ("GW_NLF_TSR_RED")
    1084                 :          28 :    write(funt,'("# GW complex dielectric tensor (red. coord.) without local field effects ")')
    1085                 :          28 :    write(funt,'(a,f7.4,a)')'# Scissor operator energy = ',BSp%mbpt_sciss*Ha_eV,' [eV]'
    1086                 :             : 
    1087                 :             :  case default
    1088   [ +  +  +  +  :         168 :    ABI_ERROR("Unknown value for what: "//TRIM(what))
             +  +  -  -  
                      - ]
    1089                 :             :  end select
    1090                 :             : 
    1091                 :             :  ! Paramaters common to the different calculations.
    1092         [ -  + ]:         168 :  if (BSp%algorithm /= BSE_ALGO_HAYDOCK) then
    1093                 :           0 :    write(funt,'(a,i0)')"# nstates included in the diagonalization = ",BSp%nstates
    1094                 :             :  end if
    1095                 :             : 
    1096         [ +  - ]:         168 :  if (BSp%algorithm == BSE_ALGO_HAYDOCK) then
    1097                 :         168 :    write(funt,'(a,2f7.4)')'# Tolerance = ',BSp%haydock_tol
    1098                 :             :  end if
    1099                 :             : 
    1100                 :         168 :  write(funt,'(a,i0)')"# npweps  = ",BSp%npweps
    1101                 :         168 :  write(funt,'(a,i0)')"# npwwfn  = ",BSp%npwwfn
    1102                 :         168 :  write(funt,'(a,i0)')"# nbands  = ",BSp%nbnds
    1103                 :         168 :  write(funt,'(a,i0)')"# loband  = ",BSp%lomo_spin(1)
    1104         [ -  + ]:         168 :  if (Bsp%nsppol==2) write(funt,'(a,i0)')"# loband(spin=2) = ",BSp%lomo_spin(2)
    1105                 :         168 :  write(funt,'(a,i0)')"# nkibz   = ",BSp%nkibz
    1106                 :         168 :  write(funt,'(a,i0)')"# nkbz    = ",BSp%nkbz
    1107                 :         168 :  write(funt,'(a,f7.4,a)')'# Lorentzian broadening = ',BSp%broad*Ha_eV,' [eV]'
    1108                 :             : 
    1109                 :             :  ! Write tensor.
    1110                 :         168 :  write(funt,'(3a)') "# omega [eV] RE(eps_11) IM(eps_11) RE(eps_22)", &
    1111                 :         168 :                     "IM(eps_22) RE(eps_33) IM(eps_33) RE(eps_12) IM(eps_12)", &
    1112                 :         336 :                     "RE(eps_13) IM(eps_13) RE(eps_23) IM(eps_23))"
    1113                 :         168 :  write(frm,*) '(f7.3,12es14.6)'
    1114         [ +  + ]:       80094 :  do io=1,BSp%nomega
    1115                 :       79926 :    omegaev = DBLE(BSp%omega(io))*Ha_eV
    1116                 :       80094 :    write(funt,frm) omegaev,(tensor(io,iq), iq=1,6)
    1117                 :             :  end do
    1118                 :             : 
    1119                 :         168 :  close(funt)
    1120                 :             : 
    1121                 :         168 : end subroutine exc_write_tensor
    1122                 :             : !!***
    1123                 :             : 
    1124                 :             : !----------------------------------------------------------------------
    1125                 :             : 
    1126                 :             : !!****f* m_exc_spectra/mdfs_ncwrite
    1127                 :             : !! NAME
    1128                 :             : !! mdfs_ncwrite
    1129                 :             : !!
    1130                 :             : !! FUNCTION
    1131                 :             : !!  Writes the MDF.nc file with the final results.
    1132                 :             : !!
    1133                 :             : !! INPUTS
    1134                 :             : !!  ncid =NC file handle
    1135                 :             : !!  Bsp<excparam>=Data type gathering the paramenters used for the Bethe-Salpeter calculation.
    1136                 :             : !!  eps_exc = Excitonic MDF
    1137                 :             : !!  eps_rpanlf = KS-RPA MDF without local-field effects.
    1138                 :             : !!  eps_gwnlf = GW-RPA MDF without local-field effects.
    1139                 :             : !!
    1140                 :             : !! OUTPUT
    1141                 :             : !!  Only writing.
    1142                 :             : !!
    1143                 :             : !! SOURCE
    1144                 :             : 
    1145                 :          44 : subroutine mdfs_ncwrite(ncid,Bsp,eps_exc,eps_rpanlf,eps_gwnlf)
    1146                 :             : 
    1147                 :             : !Arguments ------------------------------------
    1148                 :             : !scalars
    1149                 :             :  integer,intent(in) :: ncid
    1150                 :             :  type(excparam),intent(in) :: BSp
    1151                 :             : !arrays
    1152                 :             :  complex(dp),target,intent(in) :: eps_exc(BSp%nomega,BSp%nq)
    1153                 :             :  complex(dp),target,intent(in) :: eps_rpanlf(BSp%nomega,BSp%nq)
    1154                 :             :  complex(dp),target,intent(in) :: eps_gwnlf(BSp%nomega,BSp%nq)
    1155                 :             : 
    1156                 :             : !Local variables-------------------------------
    1157                 :             : !scalars
    1158                 :             :  integer :: ncerr
    1159                 :          44 :  real(dp), contiguous, pointer :: rvals(:,:,:)
    1160                 :             : ! *************************************************************************
    1161                 :             :  ! =========================
    1162                 :             :  ! === Write the dimensions
    1163                 :             :  ! =========================
    1164                 :             : 
    1165                 :             :  ncerr = nctk_defnwrite_ivars(ncid, [character(len=nctk_slen) :: &
    1166                 :             :   "mdf_version", "nsppol", "npwwfn", "npweps", "nkibz", "nkbz",&
    1167                 :             :   "nkibz_iterp", "nkbz_interp", "wtype", "interp_mode"],&
    1168                 :             :   [1, Bsp%nsppol, Bsp%npwwfn, Bsp%npweps, Bsp%nkibz, Bsp%nkbz, &
    1169   [ +  +  +  + ]:         924 :    Bsp%nkibz_interp, Bsp%nkbz_interp,Bsp%wtype, Bsp%interp_mode])
    1170         [ -  + ]:          44 :  NCF_CHECK(ncerr)
    1171                 :             : 
    1172                 :             :  ncerr = nctk_defnwrite_dpvars(ncid, [character(len=nctk_slen) :: &
    1173                 :             :   "ecutwfn", "ecuteps", "mbpt_sciss", "broad", "eps_inf"],&
    1174   [ +  +  +  + ]:         484 :   [Bsp%ecutwfn, Bsp%ecuteps, Bsp%mbpt_sciss, Bsp%broad, Bsp%eps_inf])
    1175         [ -  + ]:          44 :  NCF_CHECK(ncerr)
    1176                 :             : 
    1177                 :             :  ncerr = nctk_def_dims(ncid, [nctkdim_t("two", 2), nctkdim_t("three", 3), nctkdim_t("number_of_qpoints", Bsp%nq),&
    1178         [ +  + ]:         264 :    nctkdim_t("number_of_frequencies", Bsp%nomega), nctkdim_t("number_of_spins", bsp%nsppol)], defmode=.True.)
    1179         [ -  + ]:          44 :  NCF_CHECK(ncerr)
    1180                 :             : 
    1181                 :             :  ! Define variables.
    1182                 :             :  !arrays
    1183                 :             :  ncerr = nctk_def_arrays(ncid, [&
    1184                 :             :    nctkarr_t('qpoints', "dp", 'three, number_of_qpoints'),&
    1185                 :             :    nctkarr_t('wmesh', "dp", 'number_of_frequencies'),&
    1186                 :             :    nctkarr_t('nreh', "i", "number_of_spins"),&
    1187                 :             :    nctkarr_t('lomo_spin', "i", "number_of_spins"),&
    1188                 :             :    nctkarr_t('humo_spin', "i", "number_of_spins"),&
    1189                 :             :    nctkarr_t('exc_mdf', "dp", 'two, number_of_frequencies, number_of_qpoints'),&
    1190                 :             :    nctkarr_t('rpanlf_mdf', "dp", 'two, number_of_frequencies, number_of_qpoints'),&
    1191         [ +  + ]:         396 :    nctkarr_t('gwnlf_mdf', "dp", 'two, number_of_frequencies, number_of_qpoints')])
    1192         [ -  + ]:          44 :  NCF_CHECK(ncerr)
    1193                 :             : 
    1194                 :             :  ! Write data.
    1195         [ -  + ]:          44 :  NCF_CHECK(nctk_set_datamode(ncid))
    1196         [ -  + ]:          44 :  NCF_CHECK(nf90_put_var(ncid, vid('qpoints'), Bsp%q))
    1197         [ -  + ]:          44 :  NCF_CHECK(nf90_put_var(ncid, vid('nreh'), bsp%nreh))
    1198         [ -  + ]:          44 :  NCF_CHECK(nf90_put_var(ncid, vid('lomo_spin'), bsp%lomo_spin))
    1199         [ -  + ]:          44 :  NCF_CHECK(nf90_put_var(ncid, vid('humo_spin'), bsp%humo_spin))
    1200                 :             : 
    1201                 :             :  ! Write frequency in mesh in eV.
    1202   [ +  +  -  +  :       27589 :  NCF_CHECK(nf90_put_var(ncid, vid('wmesh'), REAL(Bsp%omega)*Ha_eV))
                   -  - ]
    1203                 :             : 
    1204         [ +  + ]:         176 :  call c_f_pointer(c_loc(eps_exc(1,1)), rvals, shape=[2, bsp%nomega, bsp%nq])
    1205         [ -  + ]:          44 :  NCF_CHECK(nf90_put_var(ncid, vid('exc_mdf'), rvals))
    1206                 :             : 
    1207         [ +  + ]:         176 :  call c_f_pointer(c_loc(eps_rpanlf(1,1)), rvals, shape=[2, bsp%nomega, bsp%nq])
    1208         [ -  + ]:          44 :  NCF_CHECK(nf90_put_var(ncid, vid('rpanlf_mdf'), rvals))
    1209                 :             : 
    1210         [ +  + ]:         176 :  call c_f_pointer(c_loc(eps_gwnlf(1,1)), rvals, shape=[2, bsp%nomega, bsp%nq])
    1211         [ -  + ]:          88 :  NCF_CHECK(nf90_put_var(ncid, vid("gwnlf_mdf"), rvals))
    1212                 :             : 
    1213                 :             : contains
    1214                 :         352 :  integer function vid(vname)
    1215                 :             :    character(len=*),intent(in) :: vname
    1216         [ +  - ]:         352 :    vid = nctk_idname(ncid, vname)
    1217                 :             :  end function vid
    1218                 :             : 
    1219                 :             : end subroutine mdfs_ncwrite
    1220                 :             : !!***
    1221                 :             : 
    1222                 :             : !!****f* m_exc_spectra/check_kramerskronig
    1223                 :             : !! NAME
    1224                 :             : !!  check_kramerskronig
    1225                 :             : !!
    1226                 :             : !! FUNCTION
    1227                 :             : !!   check Kramers Kronig
    1228                 :             : !!   \int_0^\infty d\omega' frac{\omega'}{\omega'^2 - \omega^2}
    1229                 :             : !!   Im \epsilon(\omega') = Re \epsilon(\omega)
    1230                 :             : !!
    1231                 :             : !! INPUTS
    1232                 :             : !!  n=Number of frequency points.
    1233                 :             : !!  eps(n)=Dielectric function.
    1234                 :             : !!  o(n)=Frequency mesh.
    1235                 :             : !!
    1236                 :             : !! OUTPUT
    1237                 :             : !!  Only checking.
    1238                 :             : !!
    1239                 :             : !! SOURCE
    1240                 :             : 
    1241                 :          48 : subroutine check_kramerskronig(n,o,eps)
    1242                 :             : 
    1243                 :             : !Arguments ------------------------------------
    1244                 :             : !scalars
    1245                 :             :  integer,intent(in) :: n
    1246                 :             : !arrays
    1247                 :             :  complex(dp),intent(in) :: eps(n)
    1248                 :             :  real(dp),intent(in) :: o(n)
    1249                 :             : 
    1250                 :             : !Local variables ------------------------------
    1251                 :             : !scalars
    1252                 :             :  integer :: ii,ip
    1253                 :             :  real(dp) :: omega,omegap,domega,kk,kkrms,eav
    1254                 :             :  complex(dp) :: c
    1255                 :             :  character(len=500) :: msg
    1256                 :             : !arrays
    1257                 :          96 :  real(dp) :: e1kk(n)
    1258                 :          96 :  complex(dp) :: intg(n)
    1259                 :             : !************************************************************************
    1260                 :             : ! init jmb
    1261         [ +  + ]:       42720 :  e1kk=zero
    1262         [ +  + ]:       42720 :  intg=(zero,zero)
    1263                 :             : 
    1264                 :             : ! calculate domega step and verify all
    1265                 :          48 :  domega = (o(n) - o(1)) / (n-1)
    1266                 :             : 
    1267         [ +  + ]:       42672 :  do ii=2,n
    1268         [ -  + ]:       42672 :   if (domega-(o(ii)-o(ii-1)) > tol3) then
    1269                 :           0 :     ABI_WARNING("Frequency mesh not linear. Returning")
    1270                 :           0 :     return
    1271                 :             :   end if
    1272                 :             :  end do
    1273                 :             : 
    1274         [ -  + ]:          48 :  if(o(1) > 0.1/Ha_eV) then
    1275                 :           0 :    ABI_WARNING("First frequency is not zero. Returning")
    1276                 :           0 :    return
    1277                 :             :  end if
    1278                 :             : 
    1279         [ +  + ]:          48 :  if (aimag(eps(n)) > 0.1) then
    1280                 :             :    write(msg,'(a,f12.6,3a,f12.6,2a)')&
    1281                 :          36 :    ' Im epsilon for omega= ',o(n)*Ha_eV,'eV',ch10,&
    1282                 :          36 :    ' is not yet zero, epsilon_2= ',aimag(eps(n)),ch10,&
    1283                 :          72 :    ' Kramers Kronig test could give wrong results. '
    1284                 :          36 :    ABI_WARNING(msg)
    1285                 :             :  end if
    1286                 :             : 
    1287                 :             :  ! Fill array for kramers kronig.
    1288         [ +  + ]:       42720 :  do ii=1,n
    1289                 :       42672 :    omega=o(ii)
    1290                 :       42672 :    c = (0.0,0.0)
    1291         [ +  + ]:    45902664 :    do ip=1,n
    1292         [ +  + ]:    45859992 :      if(ip == ii) cycle
    1293                 :    45817320 :      omegap = o(ip)
    1294                 :    45902664 :      c = c + omegap / (omegap**2-omega**2) * aimag(eps(ip))
    1295                 :             :    end do
    1296                 :       42720 :    e1kk(ii) = one + two/pi * domega*real(c)
    1297                 :             :  end do
    1298                 :             : 
    1299                 :             :  ! perform kramers kronig with simpson integration
    1300         [ +  + ]:       42720 :  do ii=1,n
    1301                 :       42672 :    omega=o(ii)
    1302         [ +  + ]:    45902664 :    do ip=1,n
    1303         [ +  + ]:    45859992 :      if (ip==ii) cycle
    1304                 :    45817320 :      omegap = o(ip)
    1305                 :    45902664 :      intg(ip) = omegap / (omegap**2 - omega**2) * aimag(eps(ip))
    1306                 :             :    end do
    1307                 :       42672 :    c = simpson_cplx(n,domega,intg)
    1308                 :       42720 :    e1kk(ii) = one + two/pi * real(c)
    1309                 :             :  end do
    1310                 :             : 
    1311                 :             :  !verify kramers kronig
    1312                 :             :  eav=zero; kk=zero; kkrms=zero
    1313                 :             :  do ii=1,n
    1314                 :             :    kk = kk + abs(real(eps(ii)) - e1kk(ii))
    1315                 :             :    kkrms = kkrms +(real(eps(ii)) - e1kk(ii))*(real(eps(ii)) - e1kk(ii))
    1316                 :             :    eav = eav + abs(real(eps(ii)))
    1317                 :             :  end do
    1318                 :             : 
    1319                 :          48 :  eav = eav/n
    1320                 :          48 :  kk = (kk/n)/eav
    1321                 :          48 :  kkrms = (kkrms/n) / (eav*eav)
    1322                 :             : 
    1323                 :          48 :  kk = abs(real(eps(1)) - e1kk(1)) / real(eps(1))
    1324                 :             : 
    1325                 :             :  ! write data
    1326                 :          48 :  write(msg,'(a,f7.2,a)')" The Kramers-Kronig is verified within ",100*kk,"%"
    1327                 :          48 :  call wrtout(std_out, msg)
    1328                 :             : 
    1329                 :             : ! write(std_out,'("# Kramers Kronig calculation of epsilon1")')
    1330                 :             : ! write(std_out,'("# omega   epsilon1  epsilon1kk")')
    1331                 :             : ! do ii=1,n
    1332                 :             : !   write(std_out,'(f7.3,2e15.7)') o(ii)*Ha_eV, real(eps(ii)), e1kk(ii)
    1333                 :             : ! end do
    1334                 :             : 
    1335                 :             : end subroutine check_kramerskronig
    1336                 :             : !!***
    1337                 :             : 
    1338                 :             : !----------------------------------------------------------------------
    1339                 :             : 
    1340                 :             : !!****f* m_exc_spectra/check_fsumrule
    1341                 :             : !! NAME
    1342                 :             : !!  check_fsumrule
    1343                 :             : !!
    1344                 :             : !! FUNCTION
    1345                 :             : !!   check f-sum rule
    1346                 :             : !!   \int_0^\infty d\omega \omega Im \epsilon_GG'(q,\omega) =
    1347                 :             : !!   = \frac{1}{2} \pi \omega_p^2  \frac{\rho(G-G')}{\rho(0)}
    1348                 :             : !!   versor(q+G) \dot versor(q+G')
    1349                 :             : !!   for q = G = G' = 0, it reads:
    1350                 :             : !!   \int_0^\infty d\omega \omega Im \epsilon_00(q=0,\omega) =
    1351                 :             : !!   = \pi \omega_p^2 / 2
    1352                 :             : !!   calculate only the second one
    1353                 :             : !!   calculate the integral to evaluate an omega_plasma^eff to compare with omega_plasma
    1354                 :             : !!
    1355                 :             : !! INPUTS
    1356                 :             : !!  n=Number of frequencies.
    1357                 :             : !!  o(n)=Frequency mesh.
    1358                 :             : !!  e2(n)=imaginary part of epsilon_00
    1359                 :             : !!  omegaplasma=Drude plasma frequency.
    1360                 :             : !!
    1361                 :             : !! OUTPUT
    1362                 :             : !!  Only checking.
    1363                 :             : !!
    1364                 :             : !! SOURCE
    1365                 :             : 
    1366                 :          48 : subroutine check_fsumrule(n,o,e2,omegaplasma)
    1367                 :             : 
    1368                 :             : !Arguments ------------------------------------
    1369                 :             : !scalars
    1370                 :             :  integer,intent(in) :: n
    1371                 :             :  real(dp),intent(in) :: omegaplasma
    1372                 :             : !arrays
    1373                 :             :  real(dp),intent(in) :: o(n),e2(n)
    1374                 :             : 
    1375                 :             : !Local variables ------------------------------
    1376                 :             : !scalars
    1377                 :             :  integer :: ii,ip
    1378                 :             :  real(dp) :: omegap,domega,integral,omegaplasmaeff,fsumrule
    1379                 :             :  character(len=500) :: msg
    1380                 :             : !arrays
    1381                 :          48 :  complex(dp) :: intg(n)
    1382                 :             : !************************************************************************
    1383                 :             : 
    1384                 :             :  ! calculate domega step and verify
    1385                 :          48 :  domega = (o(n) - o(1)) / (n-1)
    1386                 :             : 
    1387         [ +  + ]:       42672 :  do ii=2,n
    1388         [ -  + ]:       42672 :    if (domega-(o(ii)-o(ii-1)) > tol3) then
    1389                 :           0 :      ABI_WARNING("Frequency mesh not linear. Returning")
    1390                 :           0 :      return
    1391                 :             :    end if
    1392                 :             :  end do
    1393                 :             : 
    1394         [ -  + ]:          48 :  if (o(1) > 0.1/Ha_eV) then
    1395                 :           0 :    ABI_WARNING("First frequency is not zero. Returning")
    1396                 :           0 :    return
    1397                 :             :  end if
    1398                 :             : 
    1399         [ +  + ]:          48 :  if (e2(n) > 0.1) then
    1400                 :             :    write(msg,'(a,f12.6,3a,f12.6,2a)')&
    1401                 :          36 :    ' Im epsilon for omega= ',o(n)*Ha_eV,' eV ',ch10,&
    1402                 :          36 :    ' is not yet zero, epsilon_2= ',e2(n),ch10,&
    1403                 :          72 :    ' f-sum rule test could give wrong results.'
    1404                 :          36 :    ABI_WARNING(msg)
    1405                 :             :  end if
    1406                 :             : 
    1407                 :             :  ! integrate to obtain f-sum rule
    1408                 :          48 :  integral=zero
    1409                 :          48 :  do ip=1,n
    1410                 :             :    omegap=o(ip)
    1411                 :          48 :    integral = integral + omegap * e2(ip)
    1412                 :             :  end do
    1413                 :       42720 :  integral = domega * integral
    1414                 :             : 
    1415                 :             :  ! integrate with simpson to obtain f-sum rule
    1416         [ +  + ]:       42720 :  do ip = 1, n
    1417                 :       42672 :    omegap = o(ip)
    1418                 :       42720 :    intg(ip) = omegap * e2(ip)
    1419                 :             :  end do
    1420                 :             : 
    1421                 :          48 :  integral = real(simpson_cplx(n,domega,intg))
    1422         [ -  + ]:          48 :  if (integral < 0) then
    1423                 :           0 :    ABI_ERROR("The integral of the imaginary of dielectric function is negative !!!")
    1424                 :             :  else
    1425                 :          48 :    omegaplasmaeff = sqrt(integral*two/pi)
    1426                 :             :  end if
    1427                 :          48 :  fsumrule = abs((omegaplasmaeff - omegaplasma)) / omegaplasma
    1428                 :             : 
    1429                 :             :  ! write data
    1430                 :             :  write(msg,'(3(a,f6.2,2a))')&
    1431                 :          48 :   " omega_plasma     = ",omegaplasma*Ha_eV,   " [eV]",ch10,&
    1432                 :          48 :   " omega_plasma^eff = ",omegaplasmaeff*Ha_eV," [eV]",ch10,&
    1433                 :          96 :   " the f-sum rule is verified within ",fsumrule*100,"%",ch10
    1434                 :          48 :  call wrtout(std_out, msg)
    1435                 :             : 
    1436                 :             : end subroutine check_fsumrule
    1437                 :             : !!***
    1438                 :             : 
    1439                 :             : END MODULE m_exc_spectra
        

Generated by: LCOV version 2.3-1