LCOV - code coverage report
Current view: top level - src/71_bse - m_exc_build.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.2 % 805 734
Test Date: 2026-09-19 15:24:51 Functions: 100.0 % 3 3

            Line data    Source code
       1              : !!****m* ABINIT/m_exc_build
       2              : !! NAME
       3              : !!  m_exc_build
       4              : !!
       5              : !! FUNCTION
       6              : !!  Build the BSE Hamiltonian in the e-h representation with MPI
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 1992-2009 EXC group (L.Reining, V.Olevano, F.Sottile, S.Albrecht, G.Onida)
      10              : !!  Copyright (C) 2009-2026 ABINIT group (L.Reining, V.Olevano, F.Sottile, S.Albrecht, G.Onida, M.Giantomassi)
      11              : !!  This file is distributed under the terms of the
      12              : !!  GNU General Public License, see ~abinit/COPYING
      13              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      14              : !!
      15              : !! SOURCE
      16              : 
      17              : #if defined HAVE_CONFIG_H
      18              : #include "config.h"
      19              : #endif
      20              : 
      21              : #include "abi_common.h"
      22              : 
      23              : module m_exc_build
      24              : 
      25              :  use defs_basis
      26              :  use m_abicore
      27              :  use m_bs_defs
      28              :  use m_bse_io
      29              :  USE_MPI
      30              :  use m_xmpi
      31              :  use m_errors
      32              :  use m_screen
      33              :  use m_hdr
      34              : 
      35              :  use m_wfd,          only : wfdgw_t, wave_t, WFD_STORED
      36              :  use defs_datatypes, only : pseudopotential_type
      37              :  use m_gwdefs,       only : czero_gw, cone_gw, GW_TOLQ0
      38              :  use m_time,         only : cwtime, timab
      39              :  use m_io_tools,     only : get_unit, open_file
      40              :  use m_hide_blas,    only : xdotc, xgemv
      41              :  use m_geometry,     only : normv
      42              :  use m_crystal,      only : crystal_t
      43              :  use m_gsphere,      only : gsphere_t
      44              :  use m_vcoul,        only : vcoul_t
      45              :  use m_bz_mesh,      only : kmesh_t, findqg0
      46              :  use m_pawpwij,      only : pawpwff_t, pawpwij_t, pawpwij_init, pawpwij_free, paw_rho_tw_g
      47              :  use m_pawang,       only : pawang_type
      48              :  use m_pawtab,       only : pawtab_type
      49              :  use m_pawcprj,      only : pawcprj_type, pawcprj_alloc, pawcprj_free
      50              :  use m_paw_sym,      only : paw_symcprj_op
      51              :  use m_oscillators,  only : rho_tw_g, sym_rhotwgq0
      52              : 
      53              :  implicit none
      54              : 
      55              : #if defined HAVE_MPI1
      56              :  include 'mpif.h'
      57              : #endif
      58              : 
      59              :  private
      60              : !!***
      61              : 
      62              :  public :: exc_build_ham  !  Calculate and write the excitonic Hamiltonian to file.
      63              : !!***
      64              : 
      65              : contains
      66              : !!***
      67              : 
      68              : !!****f* m_exc_build/exc_build_block
      69              : !! NAME
      70              : !!  exc_build_block
      71              : !!
      72              : !! FUNCTION
      73              : !!  Calculate and write the excitonic Hamiltonian on an external binary file (Fortran file open
      74              : !!  in random mode) for subsequent treatment in the Bethe-Salpeter code.
      75              : !!
      76              : !! INPUTS
      77              : !!  BSp<excparam>=The parameters for the Bethe-Salpeter calculation.
      78              : !!  Cryst<crystal_t>=Info on the crystalline structure.
      79              : !!  Kmesh<kmesh_t>=The list of k-points in the BZ, IBZ and symmetry tables.
      80              : !!  Qmesh<kmesh_t>=The list of q-points for epsilon^{-1} and related symmetry tables.
      81              : !!  ktabr(nfftot_osc,BSp%nkbz)=The FFT index of $(R^{-1}(r-\tau))$ where R is symmetry needed to obtains
      82              : !!    the k-points from the irreducible image.  Used to symmetrize u_Sk where S = \transpose R^{-1}
      83              : !!  Gsph_x<gsphere_t>=Info on the G-sphere used to describe wavefunctions and W (the largest one is actually stored).
      84              : !!  Gsph_c<gsphere_t>=Info on the G-sphere used to describe the correlation part.
      85              : !!  Vcp<vcoul_t>=The Coulomb interaction in reciprocal space. A cutoff can be used
      86              : !!  screen<screen_t>=Data type gathering info and data for W.
      87              : !!  nfftot_osc=Total Number of FFT points used for the oscillator matrix elements.
      88              : !!  ngfft_osc(18)=Info on the FFT algorithm used to calculate the oscillator matrix elements.
      89              : !!  Psps<Pseudopotential_type>=Variables related to pseudopotentials
      90              : !!  Pawtab(Psps%ntypat)<pawtab_type>=PAW tabulated starting data.
      91              : !!  Pawang<pawang_type>=PAW angular mesh and related data.
      92              : !!  Paw_pwff(Cryst%ntypat*Wfd%usepaw)<pawpwff_t>=Form factor used to calculate the onsite matrix
      93              : !!    elements of a plane wave.
      94              : !!  Wfd<wfdgw_t>=Handler for the wavefunctions.
      95              : !!    prtvol=Verbosity level.
      96              : !!  rhxtwg_q0
      97              : !!  is_resonant
      98              : !!  fname
      99              : !!  comm=MPI communicator.
     100              : !!
     101              : !! OUTPUT
     102              : !!  The excitonic Hamiltonian is saved on an external binary file (see below).
     103              : !!
     104              : !! NOTES
     105              : !!  *) Version for K_V = K_C (q=0), thus KP_V = KP_C
     106              : !!  *) No exchange limit: use DFT energies in case.
     107              : !!  *) Symmetry of H(-k-k') = H*(k k') not used.
     108              : !!  *) Coulomb term can be approximated as diagonal in G.
     109              : !!  *) Valence bands treated from lomo on.
     110              : !!  *) Symmetries of the sub-blocks are used to reduce the number of elements to calculate.
     111              : !!
     112              : !!            ____________
     113              : !!           |_(cv)__(vc)_|
     114              : !!   H_exc = |  R      C  |
     115              : !!           | -C*    -R* |
     116              : !!
     117              : !!   where C is symmetric and R is Hermitian provided that the QP energies are real.
     118              : !!
     119              : !!  For nsppol=1 ==> R = diag-W+2v; C = -W+2v
     120              : !!  since the Hamiltonian can be diagonalized in the spin-singlet basis set thanks to
     121              : !!  the fact that spin triplet does not contribute to the optical limit of epsilon.
     122              : !!
     123              : !!  For nsppol=2 ==> R = diag-W+v; C = -W+v
     124              : !!  Now the matrix elements depend on the spin of the transitions but only those
     125              : !!  transitions in which the spin of the electron and of the hole are equal contribute
     126              : !!  to the macroscopic dielectric function. Moreover only the exchange term can connect transitions of different spin.
     127              : !!  When nsppol==2 the transitions are ordered using | (cv up) | (cv dwn) | (vc up) | (vc down) |
     128              : !!
     129              : !!  The resonant block is given by:
     130              : !!
     131              : !!      |  (v'c' up)       | (v'c' dwn)   |
     132              : !!      -----------------------------------           where v_{-+} = v_{+-}^H when the momentum of the photon is neglected.
     133              : !!      | [diag-W+v]++     |      v+-     | (vc up)   Note that v_{+-} is not Hermitian due to the presence of different spins.
     134              : !!  R = -----------------------------------           Actually it reduces to a Hermitian matrix when the system is not spin polarized.
     135              : !!      |     v-+          | [diag-W+v]-- | (vc dwn)  but in this case one should use nsppol=1.
     136              : !!      -----------------------------------           As a consequence the entire matrix is calculated and stored on file.
     137              : !!
     138              : !!  The coupling block is given by:
     139              : !!
     140              : !!      |  (c'v' up)   |    (c'v dwn)     |
     141              : !!      -----------------------------------           where v_{-+} = v_{+-}^t when the momentum of the photon is neglected.
     142              : !!      | [-W+v]++     |      v+-         | (vc up)   Also in this case the entire matrix v_{+-} has to be calculated
     143              : !!  C = -----------------------------------           and stored on file.
     144              : !!      |     v-+      |    [-W+v]--      | (vc dwn)
     145              : !!      -----------------------------------
     146              : !!
     147              : !! SOURCE
     148              : 
     149           23 : subroutine exc_build_block(BSp,Cryst,Kmesh,Qmesh,ktabr,Gsph_x,Gsph_c,Vcp,Wfd,screen,Hdr_bse,&
     150           23 :                            nfftot_osc,ngfft_osc,Psps,Pawtab,Pawang,Paw_pwff,rhxtwg_q0,is_resonant,fname)
     151              : 
     152              : !Arguments ------------------------------------
     153              : !scalars
     154              :  integer,intent(in) :: nfftot_osc
     155              :  character(len=*),intent(in) :: fname
     156              :  logical,intent(in) :: is_resonant
     157              :  type(excparam),intent(in) :: BSp
     158              :  type(screen_t),intent(inout) :: screen
     159              :  type(kmesh_t),intent(in) :: Kmesh,Qmesh
     160              :  type(crystal_t),intent(in) :: Cryst
     161              :  type(vcoul_t),intent(in) :: Vcp
     162              :  type(gsphere_t),intent(in) :: Gsph_x,Gsph_c
     163              :  type(Pseudopotential_type),intent(in) :: Psps
     164              :  type(Hdr_type),intent(inout) :: Hdr_bse
     165              :  type(pawang_type),intent(in) :: Pawang
     166              :  type(wfdgw_t),target,intent(inout) :: Wfd
     167              : !arrays
     168              :  integer,intent(in) :: ngfft_osc(18)
     169              :  integer,intent(in) :: ktabr(nfftot_osc,Kmesh%nbz)
     170              :  complex(gwp),intent(in) :: rhxtwg_q0(BSp%npweps,BSp%lomo_min:BSp%humo_max,BSp%lomo_min:BSp%humo_max,Wfd%nkibz,Wfd%nsppol)
     171              :  type(Pawtab_type),intent(in) :: Pawtab(Psps%ntypat*Wfd%usepaw)
     172              :  type(pawpwff_t),intent(in) :: Paw_pwff(Psps%ntypat*Wfd%usepaw)
     173              : 
     174              : !Local variables ------------------------------
     175              : !scalars
     176              :  integer,parameter :: map2sphere=1,ndat1=1,master=0
     177              :  integer(i8b) :: bsize_my_block
     178              :  integer :: nspinor,nsppol,ISg,mpi_err,tmp_size,ngx
     179              :  integer :: ik_bz,ikp_bz,col_glob,itpk_min,itpk_max
     180              :  integer :: dim_rtwg,bsh_unt,ncol,dump_unt,npweps
     181              : #ifdef HAVE_MPI_IO
     182              :  integer :: amode,mpi_fh,hmat_type,offset_err,old_type
     183              :  integer(XMPI_OFFSET_KIND) :: ehdr_offset,my_offset
     184              :  logical,parameter :: is_fortran_file=.TRUE.
     185              : #endif
     186              :  integer :: neh1,neh2,ig,nblocks
     187              :  integer :: ik_ibz,itim_k,ikp_ibz,itim_kp,isym_k,isym_kp
     188              :  integer :: iq_bz,iq_ibz,isym_q,itim_q,iqbz0,rank
     189              :  integer :: iv,ivp,ic,icp,jj,nrows,sender,my_ncols
     190              :  integer :: use_padfft,prev_nrows,spin1,spin2,block
     191              :  integer :: ierr,nproc,my_rank,mgfft_osc,fftalga_osc,comm
     192              :  integer(i8b) :: tot_nels,prev_nels,prev_ncols,nels,ir,it,itp,ist,iend,my_hsize
     193              :  real(dp) :: faq,kx_fact,cputime,walltime,gflops
     194              :  complex(sp) :: http,ctemp
     195              :  complex(dp) :: ph_mkpt,ph_mkt,ene_t,ene_tp
     196              :  logical,parameter :: with_umklp=.FALSE.
     197              :  logical :: use_mpiio,do_coulomb_term,do_exchange_term,w_is_diagonal,isirred
     198              :  logical :: is_qeq0
     199              :  character(len=500) :: msg
     200              :  type(wave_t),pointer :: wave_ck,  wave_ckp, wave_vk, wave_vkp
     201              : !arrays
     202              :  integer :: bidx(2,4),g0(3),spin_ids(2,3)
     203              :  integer(i8b) :: nels_block(3)
     204              :  integer :: my_cols(2),my_rows(2),proc_end(2),proc_start(2)
     205              :  integer :: my_extrema(2,2),sender_extrema(2,2),my_starts(2),my_ends(2)
     206           23 :  integer,allocatable :: igfftg0(:),ktabr_k(:),ktabr_kp(:),id_tab(:)
     207           23 :  integer,allocatable :: ncols_of(:)
     208           23 :  integer(i8b),allocatable :: t_start(:),t_stop(:),hsize_of(:)
     209           23 :  integer,allocatable :: col_start(:),col_stop(:)
     210           23 :  integer,allocatable :: gbound(:,:)
     211              :  real(dp) :: kbz(3),kpbz(3),qbz(3),spinrot_k(4),spinrot_kp(4),kmkp(3),tsec(2)
     212           23 :  complex(dp),allocatable :: my_bsham(:),buffer(:),buffer_2d(:,:),my_kxssp(:,:),prev_col(:)
     213              : !DBYG
     214           23 :  complex(dp),allocatable :: acoeffs(:),bcoeffs(:),ccoeffs(:) ! Coeff of W = a/q^2 + b/q + c
     215              :  integer :: a_unt, b_unt, c_unt
     216              :  complex(dp) :: aatmp, bbtmp, cctmp
     217           23 :  complex(gwp),allocatable :: aa_vpv(:),aa_cpc(:),aa_ctccp(:)
     218           23 :  complex(gwp),allocatable :: bb_vpv1(:),bb_cpc1(:),bb_ctccp1(:)
     219           23 :  complex(gwp),allocatable :: bb_vpv2(:),bb_cpc2(:),bb_ctccp2(:)
     220           23 :  complex(gwp),allocatable :: cc_vpv(:),cc_cpc(:),cc_ctccp(:)
     221           23 :  complex(dp),allocatable :: abuffer(:),aprev_col(:)
     222           23 :  complex(dp),allocatable :: bbuffer(:),bprev_col(:)
     223           23 :  complex(dp),allocatable :: cbuffer(:),cprev_col(:)
     224              :  character(len=fnlen) :: tmpfname
     225              :  integer :: ii
     226              : !END DBYG
     227           23 :  complex(gwp),allocatable :: vc_sqrt_qbz(:), rhotwg1(:),rhotwg2(:),rhxtwg_vpv(:),rhxtwg_cpc(:),ctccp(:)
     228           23 :  complex(gwp),target,allocatable :: ur_ckp(:),ur_vkp(:),ur_vk(:),ur_ck(:)
     229           23 :  complex(gwp),contiguous, pointer :: ptur_ckp(:),ptur_vkp(:),ptur_vk(:),ptur_ck(:)
     230           23 :  type(pawcprj_type),target,allocatable :: Cp_tmp1(:,:),Cp_tmp2(:,:)
     231           23 :  type(pawcprj_type),target,allocatable :: Cp_tmp3(:,:),Cp_tmp4(:,:)
     232           23 :  type(pawcprj_type),allocatable :: Cp_ckp(:,:),Cp_vkp(:,:)
     233           23 :  type(pawcprj_type),allocatable :: Cp_vk(:,:),Cp_ck(:,:)
     234           23 :  type(pawcprj_type),pointer :: ptcp_ckp(:,:),ptcp_vkp(:,:),ptcp_vk(:,:),ptcp_ck(:,:)
     235           23 :  type(pawpwij_t),allocatable :: Pwij_q(:)
     236              : #ifdef HAVE_MPI_IO
     237              :  integer(XMPI_OFFSET_KIND) :: tmp_off,my_offpad
     238           23 :  integer(XMPI_OFFSET_KIND),allocatable :: bsize_frecord(:),offset_of_block(:)
     239              : #endif
     240              : #ifdef DEV_MG_DEBUG_MODE
     241              :  integer,allocatable :: ttp_check(:,:)
     242              : #endif
     243              : !************************************************************************
     244              : 
     245           23 :  call timab(680,1,tsec)
     246           23 :  call timab(681,1,tsec)
     247              : 
     248              :  DBG_ENTER("COLL")
     249              : 
     250           23 :  ABI_CHECK(Wfd%nspinor==1,"nspinor==2 not coded")
     251           92 :  ABI_CHECK(nfftot_osc==PRODUCT(ngfft_osc(1:3)),"mismatch in FFT size")
     252              : 
     253           23 :  if (Wfd%nsppol==2) then
     254            1 :    ABI_WARNING("nsppol==2 is still under testing")
     255              :  end if
     256              :  ! MPI variables.
     257           23 :  comm    = Wfd%comm
     258           23 :  nproc   = Wfd%nproc
     259           23 :  my_rank = Wfd%my_rank
     260              : 
     261              :  ! Basic constants.
     262           23 :  nspinor = Wfd%nspinor
     263           23 :  nsppol  = Wfd%nsppol
     264           23 :  dim_rtwg=1; faq = one/(Cryst%ucvol*Kmesh%nbz)
     265           23 :  npweps = Bsp%npweps
     266              : 
     267              :  ! Prepare the FFT tables to have u(r) on the ngfft_osc mesh.
     268           92 :  mgfft_osc = MAXVAL(ngfft_osc(1:3))
     269           23 :  fftalga_osc = ngfft_osc(7)/100
     270           92 :  if ( ANY(ngfft_osc(1:3) /= Wfd%ngfft(1:3)) ) call wfd%change_ngfft(Cryst,Psps,ngfft_osc)
     271              : 
     272           69 :  ABI_MALLOC(igfftg0,(npweps))
     273           69 :  ABI_MALLOC(ktabr_k,(nfftot_osc))
     274           46 :  ABI_MALLOC(ktabr_kp,(nfftot_osc))
     275           46 :  ABI_MALLOC(id_tab,(nfftot_osc))
     276       482671 :  id_tab = (/(ic, ic=1,nfftot_osc)/)
     277              : 
     278              :  ! Workspace arrays for wavefunctions and oscillator matrix elements.
     279           69 :  ABI_MALLOC(rhxtwg_vpv,(npweps))
     280           46 :  ABI_MALLOC(rhxtwg_cpc,(npweps))
     281              : 
     282           23 :  if (BSp%prep_interp) then
     283            1 :    call wrtout(std_out,"Preparing BSE interpolation")
     284            2 :    ABI_MALLOC(aa_vpv,(npweps))
     285            2 :    ABI_MALLOC(bb_vpv1,(npweps))
     286            2 :    ABI_MALLOC(bb_vpv2,(npweps))
     287            2 :    ABI_MALLOC(cc_vpv,(npweps))
     288            2 :    ABI_MALLOC(aa_cpc,(npweps))
     289            2 :    ABI_MALLOC(bb_cpc1,(npweps))
     290            2 :    ABI_MALLOC(bb_cpc2,(npweps))
     291            2 :    ABI_MALLOC(cc_cpc,(npweps))
     292              :  end if
     293              : 
     294           69 :  ABI_MALLOC(ur_ckp,(nspinor*nfftot_osc))
     295           46 :  ABI_MALLOC(ur_vkp,(nspinor*nfftot_osc))
     296           46 :  ABI_MALLOC(ur_ck ,(nspinor*nfftot_osc))
     297           46 :  ABI_MALLOC(ur_vk ,(nspinor*nfftot_osc))
     298              : 
     299           23 :  if (Wfd%usepaw==1) then
     300           14 :    ABI_MALLOC(Cp_vk,(Wfd%natom,nspinor))
     301            2 :    call pawcprj_alloc(Cp_vk,0,Wfd%nlmn_atm)
     302           14 :    ABI_MALLOC(Cp_ck,(Wfd%natom,nspinor))
     303            2 :    call pawcprj_alloc(Cp_ck,0,Wfd%nlmn_atm)
     304           14 :    ABI_MALLOC(Cp_ckp,(Wfd%natom,nspinor))
     305            2 :    call pawcprj_alloc(Cp_ckp,0,Wfd%nlmn_atm)
     306           14 :    ABI_MALLOC(Cp_vkp,(Wfd%natom,nspinor))
     307            2 :    call pawcprj_alloc(Cp_vkp,0,Wfd%nlmn_atm)
     308              : 
     309           14 :    ABI_MALLOC(Cp_tmp1,(Wfd%natom,nspinor))
     310            2 :    call pawcprj_alloc(Cp_tmp1,0,Wfd%nlmn_atm)
     311           14 :    ABI_MALLOC(Cp_tmp2,(Wfd%natom,nspinor))
     312            2 :    call pawcprj_alloc(Cp_tmp2,0,Wfd%nlmn_atm)
     313           14 :    ABI_MALLOC(Cp_tmp3,(Wfd%natom,nspinor))
     314            2 :    call pawcprj_alloc(Cp_tmp3,0,Wfd%nlmn_atm)
     315           14 :    ABI_MALLOC(Cp_tmp4,(Wfd%natom,nspinor))
     316            2 :    call pawcprj_alloc(Cp_tmp4,0,Wfd%nlmn_atm)
     317              :  end if
     318              :  !
     319              :  ! Identify the index of q==0
     320           23 :  iqbz0=0
     321         1079 :  do iq_bz=1,Qmesh%nbz
     322         1446 :    if (ALL(ABS(Qmesh%bz(:,iq_bz))<tol3)) iqbz0 = iq_bz
     323              :  end do
     324           23 :  ABI_CHECK(iqbz0/=0,"q=0 not found")
     325              :  !
     326              :  ! Treat the spin polarization.
     327           69 :  spin_ids(:,1) = (/1,1/)
     328           69 :  spin_ids(:,2) = (/2,2/)
     329           69 :  spin_ids(:,3) = (/1,2/)
     330              : 
     331           23 :  nblocks=1
     332           23 :  kx_fact=two
     333           23 :  nels_block(:)=0
     334           23 :  nels_block(1)=BSp%nreh(1)*(BSp%nreh(1)+1_i8b)/2
     335           23 :  tot_nels=nels_block(1)
     336              : 
     337           23 :  if (nsppol==2) then
     338            1 :    nblocks=3
     339            1 :    kx_fact=one
     340              :    nels_block(1) = BSp%nreh(1)*(BSp%nreh(1)+1_i8b)/2   ! Only the upper triangle for block 1 and 2
     341            1 :    nels_block(2) = BSp%nreh(2)*(BSp%nreh(2)+1_i8b)/2
     342            1 :    nels_block(3) = BSp%nreh(1)*BSp%nreh(2)*1_i8b       ! Note: Block 3 does not have symmetries.
     343            4 :    tot_nels= SUM(nels_block)
     344              :  end if
     345              :  !
     346              :  ! Distribute the calculation of the matrix elements among the nodes.
     347              :  ! * tstart and t_stop give the initial and final transition index treated by each node.
     348              :  ! * my_hsize is the number of transitions treated by this processor
     349              :  ! * my_cols(1:2) gives the initial and final column treated by this node.
     350              :  !
     351              :  use_mpiio=.FALSE.
     352              : #ifdef HAVE_MPI_IO
     353              :  use_mpiio = (nproc>1)
     354              : #endif
     355           23 :  use_mpiio=.FALSE.
     356              :  !use_mpiio=.TRUE.
     357              : 
     358           23 :  if (is_resonant) then
     359              :    if (use_mpiio) then
     360              :      write(msg,'(2a,f6.2,a)')&
     361              :       ". Writing resonant excitonic Hamiltonian on file "//TRIM(fname)," via MPI-IO; file size= ",two*tot_nels*dp*b2Gb," [Gb]."
     362              :    else
     363              :      write(msg,'(2a,f6.2,a)')&
     364           22 :       ". Writing resonant excitonic Hamiltonian on file "//TRIM(fname),"; file size= ",two*dp*tot_nels*b2Gb," [Gb]."
     365              :    end if
     366              :  else
     367              :    if (use_mpiio) then
     368              :      write(msg,'(2a,f6.2,a)')&
     369              :       ". Writing coupling excitonic Hamiltonian on file "//TRIM(fname)," via MPI-IO; file size= ",tot_nels*2*dp*b2Gb," [Gb]."
     370              :    else
     371              :      write(msg,'(2a,f6.2,a)')&
     372            1 :       ". Writing coupling excitonic Hamiltonian on file "//TRIM(fname),"; file size= ",two*dp*tot_nels*b2Gb," [Gb]."
     373              :    end if
     374              :  end if
     375           69 :  call wrtout([std_out, ab_out], msg, do_flush=.True.)
     376              : 
     377              :  ! Master writes the BSE header with Fortran IO.
     378           23 :  if (my_rank==master) then
     379           19 :    if (open_file(fname,msg,newunit=bsh_unt,form="unformatted",action="write") /= 0) then
     380            0 :       ABI_ERROR(msg)
     381              :    end if
     382           19 :    call exc_write_bshdr(bsh_unt,Bsp,Hdr_bse)
     383              :    ! To force the writing (needed for MPI-IO).
     384           19 :    close(bsh_unt)
     385              : 
     386           19 :    if (.not.use_mpiio) then ! Reopen the file and skip the header.
     387           19 :      if (open_file(fname,msg,newunit=bsh_unt,form="unformatted",action="readwrite") /= 0) then
     388            0 :         ABI_ERROR(msg)
     389              :      end if
     390           19 :      call exc_skip_bshdr(bsh_unt,ierr)
     391              :    end if
     392              : 
     393           19 :    if (BSp%prep_interp) then
     394            1 :      tmpfname = fname
     395            1 :      ii = LEN_TRIM(fname)
     396            1 :      tmpfname(ii-2:ii+1) = 'ABSR'
     397            1 :      if (open_file(tmpfname,msg,newunit=a_unt,form='unformatted',action="write") /= 0) then
     398            0 :        ABI_ERROR(msg)
     399              :      end if
     400            1 :      tmpfname(ii-2:ii+1) = 'BBSR'
     401            1 :      if (open_file(tmpfname,msg,newunit=b_unt,form='unformatted',action="write") /= 0) then
     402            0 :        ABI_ERROR(msg)
     403              :      end if
     404            1 :      tmpfname(ii-2:ii+1) = 'CBSR'
     405            1 :      if (open_file(tmpfname,msg,newunit=c_unt,form='unformatted',action="write") /= 0) then
     406            0 :        ABI_ERROR(msg)
     407              :      end if
     408            1 :      call exc_write_bshdr(a_unt,Bsp,Hdr_bse)
     409            1 :      call exc_write_bshdr(b_unt,Bsp,Hdr_bse)
     410            1 :      call exc_write_bshdr(c_unt,Bsp,Hdr_bse)
     411            1 :      close(a_unt)
     412            1 :      close(b_unt)
     413            1 :      close(c_unt)
     414            3 :      if (.not.use_mpiio) then ! Reopen the file and skip the header.
     415            1 :        tmpfname(ii-2:ii+1) = 'ABSR'
     416            1 :        if (open_file(tmpfname,msg,newunit=a_unt,form='unformatted',action="readwrite") /= 0) then
     417            0 :           ABI_ERROR(msg)
     418              :        end if
     419            1 :        call exc_skip_bshdr(a_unt,ierr)
     420            1 :        tmpfname(ii-2:ii+1) = 'BBSR'
     421            1 :        if (open_file(tmpfname,msg,newunit=b_unt,form='unformatted',action="readwrite") /= 0) then
     422            0 :           ABI_ERROR(msg)
     423              :        end if
     424            1 :        call exc_skip_bshdr(b_unt,ierr)
     425            1 :        tmpfname(ii-2:ii+1) = 'CBSR'
     426            1 :        if (open_file(tmpfname,msg,newunit=c_unt,form='unformatted',action="readwrite") /= 0) then
     427            0 :           ABI_ERROR(msg)
     428              :        end if
     429            1 :        call exc_skip_bshdr(c_unt,ierr)
     430              :      end if
     431              :    end if
     432              :  end if
     433              : 
     434           23 :  call xmpi_barrier(comm)
     435              : 
     436              :  if (use_mpiio) then
     437              : #ifdef HAVE_MPI_IO
     438              :    ! Open the file with MPI-IO
     439              :    amode = MPI_MODE_RDWR
     440              :    !amode = MPI_MODE_CREATE + MPI_MODE_RDWR,
     441              : 
     442              :    call MPI_FILE_OPEN(comm, fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
     443              :    ABI_CHECK_MPI(mpi_err,"opening: "//TRIM(fname))
     444              : 
     445              :    ! Skip the header.
     446              :    call exc_skip_bshdr_mpio(mpi_fh,xmpio_collective,ehdr_offset)
     447              : 
     448              :    ! Precompute the offset of the each block including the Fortran markers.
     449              :    ABI_MALLOC(offset_of_block,(nblocks))
     450              :    offset_of_block(1) = ehdr_offset
     451              :    do block=2,nblocks
     452              :      tmp_off = offset_of_block(block-1) + nels_block(block-1)*xmpi_bsize_dpc
     453              :      tmp_off = tmp_off + Bsp%nreh(block-1)*2*xmpio_bsize_frm  ! markers.
     454              :      offset_of_block(block) = tmp_off
     455              :    end do
     456              : #endif
     457              :  end if
     458              : 
     459           23 :  call timab(681,2,tsec)
     460              : 
     461           47 :  do block=1,nsppol
     462              :    !
     463              :    ! Indices used to loop over bands.
     464              :    ! bidx contains the starting and final indices used to loop over bands.
     465              :    !
     466              :    !      (b3,b4)
     467              :    !         |... ...|
     468              :    ! (b1,b2) |... ...|
     469              :    !
     470              :    ! Resonant matrix is given by
     471              :    !      (v',c')
     472              :    !       |... ...|
     473              :    ! (v,c) |... ...|
     474              :    !
     475              :    ! Coupling matrix is given by
     476              :    !       (c',v')
     477              :    !       |... ...|
     478              :    ! (v,c) |... ...|
     479              : 
     480           24 :    if (is_resonant) then
     481           69 :      bidx(:,1) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b1
     482           69 :      bidx(:,2) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b2
     483           69 :      bidx(:,3) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b3
     484           69 :      bidx(:,4) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b4
     485              :    else
     486            3 :      bidx(:,1) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b1
     487            3 :      bidx(:,2) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b2
     488            3 :      bidx(:,3) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b3
     489            3 :      bidx(:,4) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b4
     490              :    end if
     491              : 
     492           24 :    spin1 = spin_ids(1,block)
     493           24 :    spin2 = spin_ids(2,block)
     494              : 
     495           24 :    do_coulomb_term  = (Bsp%use_coulomb_term .and. (spin1==spin2))
     496           24 :    do_exchange_term = (Bsp%exchange_term>0)
     497           24 :    w_is_diagonal    = BSp%use_diagonal_Wgg
     498              :    !
     499              :    ! Distribution of the matrix elements among the nodes.
     500              :    ! Note that rank0 will get the first transitions.
     501           24 :    nels=nels_block(block)
     502           72 :    ABI_MALLOC(t_start,(0:nproc-1))
     503           48 :    ABI_MALLOC(t_stop,(0:nproc-1))
     504           24 :    call xmpi_split_work2_i8b(nels,nproc,t_start,t_stop)
     505              : 
     506           48 :    ABI_MALLOC(hsize_of,(0:nproc-1))
     507           62 :    hsize_of=0
     508           62 :    do rank=0,nproc-1
     509           62 :      if (t_stop(rank)>=t_start(rank)) hsize_of(rank) = t_stop(rank)-t_start(rank)+1
     510              :      !write(std_out,*)"nels",nels,hsize_of(rank)
     511              :    end do
     512              : 
     513           24 :    my_hsize = hsize_of(my_rank)
     514           24 :    if (my_hsize<=0) then
     515            0 :      write(msg,'(a,i0)')"Wrong number of transitions: my_hsize= ",my_hsize
     516            0 :      ABI_ERROR(msg)
     517              :    end if
     518           24 :    if (my_hsize /= INT(my_hsize,KIND=i4b)) then
     519            0 :      write(msg,'(a,i0)')"Size of local block too large for a default integer, Increase the number of CPUs: my_hsize= ",my_hsize
     520            0 :      ABI_ERROR(msg)
     521              :    end if
     522              : 
     523           24 :    my_cols=0
     524         9272 :    do itp=1,Bsp%nreh(block)
     525      2182216 :      do it=1,itp
     526      2172944 :        ir = it + itp*(itp-1_i8b)/2
     527      2172944 :        if (ir==t_start(my_rank)) then
     528           24 :          my_rows(1) = it
     529           24 :          my_cols(1) = itp
     530              :        end if
     531      2182192 :        if (ir==t_stop(my_rank)) then
     532           24 :          my_rows(2) = it
     533           24 :          my_cols(2) = itp
     534              :        end if
     535              :      end do
     536              :    end do
     537              : 
     538           72 :    my_starts = [my_rows(1),my_cols(1)]
     539           24 :    my_ends   = [my_rows(2),my_cols(2)]
     540              :    !
     541              :    ! Announce the treatment of submatrix treated by each node.
     542           24 :    bsize_my_block = 2*dp*my_hsize
     543           24 :    write(msg,'(4(a,i0))')' Treating ',my_hsize,'/',nels,' matrix elements, from column ',my_cols(1),' up to column ',my_cols(2)
     544           24 :    call wrtout(std_out, msg)
     545              : 
     546           24 :    if (is_resonant) then
     547           23 :      write(msg,'(a,f8.1,a)')' Calculating resonant blocks. Memory required: ',bsize_my_block*b2Mb,' [Mb] <<< MEM'
     548              :    else
     549            1 :      write(msg,'(a,f8.1,a)')' Calculating coupling blocks. Memory required: ',bsize_my_block*b2Mb,' [Mb] <<< MEM'
     550              :    end if
     551           24 :    call wrtout(std_out, msg)
     552              : 
     553              :    ! Allocate big (scalable) buffer to store the BS matrix on this node.
     554           72 :    ABI_MALLOC_OR_DIE(my_bsham,(t_start(my_rank):t_stop(my_rank)), ierr)
     555              : 
     556           24 :    if (BSp%prep_interp) then
     557              :      ! Allocate big (scalable) buffers to store a,b,c coefficients
     558            2 :      ABI_MALLOC_OR_DIE(acoeffs,(t_start (my_rank):t_stop(my_rank)), ierr)
     559            2 :      ABI_MALLOC_OR_DIE(bcoeffs,(t_start(my_rank):t_stop(my_rank)), ierr)
     560            2 :      ABI_MALLOC_OR_DIE(ccoeffs,(t_start(my_rank):t_stop(my_rank)), ierr)
     561              :    end if
     562              : 
     563           24 :    if (do_coulomb_term) then ! Construct Coulomb term.
     564              : 
     565           24 :      call timab(682,1,tsec) ! exc_build_ham(Coulomb)
     566              : 
     567           24 :      write(msg,'(a,2i2,a)')" Calculating direct Coulomb term for (spin1,spin2) ",spin1,spin2," using full W_{GG'} ..."
     568           24 :      if (w_is_diagonal) then
     569              :        write(msg,'(a,2i2,a)')&
     570            2 :          " Calculating direct Coulomb term for (spin1, spin2) ",spin1,spin2," using diagonal approximation for W_{GG'} ..."
     571              :      end if
     572           24 :      call wrtout(std_out, msg)
     573              : 
     574           72 :      ABI_MALLOC(ctccp,(npweps))
     575              : 
     576           24 :      if (BSp%prep_interp) then
     577            2 :        ABI_MALLOC(aa_ctccp,(npweps))
     578            2 :        ABI_MALLOC(bb_ctccp1,(npweps))
     579            2 :        ABI_MALLOC(bb_ctccp2,(npweps))
     580            2 :        ABI_MALLOC(cc_ctccp,(npweps))
     581              :      end if
     582              : 
     583           48 :      ABI_MALLOC(vc_sqrt_qbz,(npweps))
     584              : 
     585              : #ifdef DEV_MG_DEBUG_MODE
     586              :      ABI_MALLOC(ttp_check,(BSp%nreh(block),BSp%nreh(block)))
     587              :      ttp_check=0
     588              : #endif
     589              : 
     590         1112 :      do ikp_bz=1,BSp%nkbz ! Loop over kp
     591              :        ! NOTE: this way of looping is good for bulk but it's not optimal in the
     592              :        !       case of systems sampled only at Gamma e.g. isolated systems in which
     593              :        !       one should take advantage of Hermiticity by looping over c-v !!!!
     594              : 
     595              :        ! Check whether (vp,cp,ikp_bz,spin2) belongs to the set of columns treated by me for some vp,cp
     596              :        ! Be careful since vcks2t contains zeros corresponding to transitions that should be skipped.
     597        13456 :        itpk_min = MINVAL(Bsp%vcks2t(:,:,ikp_bz,spin2), MASK=(Bsp%vcks2t(:,:,ikp_bz,spin2)>0) )
     598        13456 :        itpk_max = MAXVAL(Bsp%vcks2t(:,:,ikp_bz,spin2))
     599         1088 :        if (my_cols(2)<itpk_min .or. my_cols(1)>itpk_max) CYCLE
     600              : 
     601          836 :        write(msg,'(3(a,i0))')" status: ",ikp_bz,"/",BSp%nkbz," done by node ",my_rank
     602          836 :        call wrtout(std_out, msg, do_flush=.True.)
     603              : 
     604              :        ! * Get ikp_ibz, non-symmorphic phase, ph_mkpt, and symmetries from ikp_bz.
     605          836 :        call kmesh%get_BZ_item(ikp_bz,kpbz,ikp_ibz,isym_kp,itim_kp,ph_mkpt,isirred=isirred)
     606              :        !ABI_CHECK(isirred,"not irred!")
     607              :        !ABI_CHECK(ph_mkpt == cone, "Wrong phase!")
     608              : 
     609      6059836 :        ktabr_kp(:) = ktabr(:,ikp_bz)
     610         4180 :        spinrot_kp(:)=Cryst%spinrot(:,isym_kp)
     611              :        !ABI_CHECK(ALL(ktabr_kp == id_tab), "wrong tab")
     612              : 
     613        23600 :        do ik_bz=1,ikp_bz ! Loop over k
     614              :          !
     615              :          ! * Get ik_ibz, non-symmorphic phase, ph_mkt, and symmetries from ik_bz
     616        22740 :          call kmesh%get_BZ_item(ik_bz,kbz,ik_ibz,isym_k,itim_k,ph_mkt,isirred=isirred)
     617              :          !ABI_CHECK(isirred,"not irred!")
     618              :          !ABI_CHECK(ph_mkt == cone, "Wrong phase!")
     619              : 
     620    172008240 :          ktabr_k(:) = ktabr(:,ik_bz)
     621       113700 :          spinrot_k(:)=Cryst%spinrot(:,isym_k)
     622              :          !ABI_CHECK(ALL(ktabr_k == id_tab), "wrong tab")
     623              :          !if(itim_k==2) CYCLE ! time-reversal or not
     624              :          !
     625              :          ! * Find q = K-KP-G0 in the full BZ.
     626        90960 :          kmkp = Kmesh%bz(:,ik_bz) - Kmesh%bz(:,ikp_bz)
     627        22740 :          call findqg0(iq_bz,g0,kmkp,Qmesh%nbz,Qmesh%bz,BSp%mG0)
     628              : 
     629              :          ! Evaluate the tables needed for the padded FFT performed in rhotwg. Note that we have
     630              :          ! to pass G-G0 to sphereboundary instead of G as we need FFT results on the shifted G-sphere,
     631              :          ! If Gamma is not inside G-G0 one has to disable FFT padding as sphereboundary will give wrong tables.
     632              :          ! * Get the G-G0 shift for the FFT of the oscillators.
     633              :          !
     634        90960 :          ABI_MALLOC(gbound,(2*mgfft_osc+8,2))
     635        22740 :          call Gsph_c%fft_tabs(g0,mgfft_osc,ngfft_osc,use_padfft,gbound,igfftg0)
     636        22740 :          if ( ANY(fftalga_osc == (/2,4/)) ) use_padfft=0 ! Pad-FFT is not coded in rho_tw_g
     637        22740 :          if (use_padfft==0) then
     638           28 :            ABI_FREE(gbound)
     639           56 :            ABI_MALLOC(gbound,(2*mgfft_osc+8,2*use_padfft))
     640              :          end if
     641              :          !
     642              :          ! Get iq_ibz, and symmetries from iq_bz
     643        22740 :          call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q)
     644        22740 :          is_qeq0 = (normv(qbz,Cryst%gmet,'G')<GW_TOLQ0)
     645              : 
     646              :          ! Symmetrize em1(omega=0)
     647        22740 :          call screen%rotate_iqbz(iq_bz, Cryst, Gsph_c, Qmesh, Vcp)
     648              : 
     649              :          ! Set up table of |q_BZ+G|
     650        22740 :          if (iq_ibz==1) then
     651        40208 :            do ig=1,npweps
     652        39372 :              isg = Gsph_c%rottb(ig,itim_q,isym_q)
     653        40208 :              vc_sqrt_qbz(isg)=Vcp%vcqlwl_sqrt(ig,1)
     654              :            end do
     655              :          else
     656      1014192 :            do ig=1,npweps
     657       992288 :              isg = Gsph_c%rottb(ig,itim_q,isym_q)
     658      1014192 :              vc_sqrt_qbz(isg) = Vcp%vc_sqrt(ig,iq_ibz)
     659              :            end do
     660              :          end if
     661              : 
     662              :          ! === Evaluate oscillator matrix elements ===
     663              :          ! * $ <phj/r|e^{-i(q+G)}|phi/r> - <tphj/r|e^{-i(q+G)}|tphi/r> $ in packed form.
     664        22740 :          if (Wfd%usepaw==1.and.ik_bz/=ikp_bz) then
     665         4108 :            ABI_MALLOC(Pwij_q,(Cryst%ntypat))
     666         1020 :            call pawpwij_init(Pwij_q,npweps,Qmesh%bz(:,iq_bz),Gsph_c%gvec,Cryst%rprimd,Psps,Pawtab,Paw_pwff)
     667              :          end if
     668              : 
     669              :          ! =======================================
     670              :          ! === Loop over the four band indices ===
     671              :          ! =======================================
     672        90388 :          do ic=bidx(1,2),bidx(2,2) !do ic=BSp%lumo,BSp%nbnds
     673              : 
     674        67648 :            ABI_CHECK(wfd%get_wave_ptr(ic, ik_ibz, spin1, wave_ck, msg) == 0, msg)
     675        67648 :            if (wave_ck%has_ur == WFD_STORED) then
     676        67420 :              ptur_ck => wave_ck%ur
     677              :            else
     678          228 :              call wfd%get_ur(ic,ik_ibz,spin1,ur_ck)
     679          228 :              ptur_ck => ur_ck
     680              :            end if
     681              :            !
     682              :            ! Get cprj for this (c,kbz,s1) in the BZ.
     683              :            ! phase due to the umklapp G0 in k-q is already included.
     684        67648 :            if (Wfd%usepaw==1) then
     685         4296 :              if (wave_ck%has_cprj == WFD_STORED) then
     686         4296 :                ptcp_ck => wave_ck%cprj
     687              :              else
     688            0 :                call wfd%get_cprj(ic,ik_ibz,spin1,Cryst,Cp_tmp1,sorted=.FALSE.)
     689            0 :                ptcp_ck => Cp_tmp1
     690              :              end if
     691         4296 :              call paw_symcprj_op(ik_bz,nspinor,1,Cryst,Kmesh,Pawtab,Pawang,ptcp_ck,Cp_ck)
     692              :            end if
     693              : 
     694       306004 :            do icp=bidx(1,4),bidx(2,4)  !do icp=BSp%lumo,BSp%nbnds
     695              :              ! Calculate matrix-elements rhxtwg_cpc
     696              :              !
     697       215616 :              if (ik_bz==ikp_bz) then ! Already in memory.
     698         8688 :                rhxtwg_cpc(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,icp,ic,ik_ibz,spin1),Gsph_c)
     699              : 
     700              :              else
     701              :                ! Calculate matrix element from wfr.
     702              :                ! TODO: change the order of the loops.
     703              : 
     704       206928 :                ABI_CHECK(wfd%get_wave_ptr(icp, ikp_ibz, spin2, wave_ckp, msg) == 0, msg)
     705       206928 :                if (wave_ckp%has_ur == WFD_STORED) then
     706       206724 :                  ptur_ckp => wave_ckp%ur
     707              :                else
     708          204 :                  call wfd%get_ur(icp,ikp_ibz,spin2,ur_ckp)
     709          204 :                  ptur_ckp => ur_ckp
     710              :                end if
     711              : 
     712              :                ! Load cprj for this (c,k,s2) in the BZ.
     713              :                ! Do not care about umklapp G0 in k-q as the phase is already included.
     714       206928 :                if (Wfd%usepaw==1) then
     715        15984 :                  if (wave_ckp%has_cprj == WFD_STORED) then
     716        15984 :                    ptcp_ckp =>  wave_ckp%cprj
     717              :                  else
     718            0 :                    call wfd%get_cprj(icp,ikp_ibz,spin2,Cryst,Cp_tmp2,sorted=.FALSE.)
     719            0 :                    ptcp_ckp =>  Cp_tmp2
     720              :                  end if
     721        15984 :                  call paw_symcprj_op(ikp_bz,nspinor,1,Cryst,Kmesh,Pawtab,Pawang,ptcp_ckp,Cp_ckp)
     722              :                end if
     723              : 
     724              :                call rho_tw_g(nspinor,npweps,nfftot_osc,ndat1,ngfft_osc,map2sphere,use_padfft,igfftg0,gbound,&
     725              :                  ptur_ckp,itim_kp,ktabr_kp,ph_mkpt,spinrot_kp,&
     726              :                  ptur_ck ,itim_k ,ktabr_k ,ph_mkt ,spinrot_k ,&
     727       206928 :                  dim_rtwg,rhxtwg_cpc)
     728              : 
     729       206928 :                if (Wfd%usepaw==1) then ! Add PAW onsite contribution.
     730        15984 :                  call paw_rho_tw_g(cryst,Pwij_q,npweps,dim_rtwg,nspinor,Gsph_c%gvec, Cp_ckp,Cp_ck,rhxtwg_cpc)
     731              :                end if
     732              :              end if
     733              : 
     734       215616 :              if (BSp%prep_interp) then
     735        30528 :                aa_cpc = rhxtwg_cpc
     736        29376 :                aa_cpc(2:) = czero
     737        30528 :                bb_cpc1 = vc_sqrt_qbz*rhxtwg_cpc
     738          576 :                bb_cpc1(1) = czero
     739        30528 :                bb_cpc2 = rhxtwg_cpc
     740        29376 :                bb_cpc2(2:) = czero
     741              : 
     742          576 :                if(ik_bz == ikp_bz) then
     743              :                  ! Enforce orthogonality of the wavefunctions.
     744          128 :                  if(icp == ic) then
     745           32 :                    aa_cpc(1) = cone
     746           32 :                    bb_cpc2(1) = cone
     747              :                  else
     748           96 :                    aa_cpc(1) = czero
     749           96 :                    bb_cpc2(1) = czero
     750              :                  end if
     751              :                end if
     752              : 
     753              :                ! MG TODO: a does not require a call to w0gemv
     754          576 :                call screen%w0gemv("C",npweps,nspinor,w_is_diagonal,cone_gw,czero_gw,aa_cpc,aa_ctccp)
     755          576 :                call screen%w0gemv("C",npweps,nspinor,w_is_diagonal,cone_gw,czero_gw,bb_cpc1,bb_ctccp1)
     756          576 :                call screen%w0gemv("C",npweps,nspinor,w_is_diagonal,cone_gw,czero_gw,bb_cpc2,bb_ctccp2)
     757              : 
     758        30528 :                cc_cpc = vc_sqrt_qbz*rhxtwg_cpc
     759          576 :                cc_cpc(1) = czero
     760              : 
     761          576 :                call screen%w0gemv("C",npweps,nspinor,w_is_diagonal,cone_gw,czero_gw,cc_cpc,cc_ctccp)
     762              :              end if
     763              : 
     764              :              ! Prepare sum_GG' rho_c'c*(G) W_qbz(G,G') rho_v'v(G')
     765              :              ! First sum on G: sum_G rho_c'c(G) W_qbz*(G,G') (W_qbz conjugated)
     766      9953856 :              rhxtwg_cpc = rhxtwg_cpc * vc_sqrt_qbz
     767       215616 :              call screen%w0gemv("C",npweps,nspinor,w_is_diagonal,cone_gw,czero_gw,rhxtwg_cpc,ctccp)
     768              : 
     769       921936 :              do iv=bidx(1,1),bidx(2,1)    !do iv=BSp%lomo,BSp%homo
     770       638672 :                it = BSp%vcks2t(iv,ic,ik_bz,spin1); if (it==0) CYCLE ! ir-uv-cutoff
     771       638672 :                ene_t = BSp%Trans(it,spin1)%en
     772              : 
     773              :                ! TODO: use this but change the order of the loops.
     774       638672 :                ABI_CHECK(wfd%get_wave_ptr(iv, ik_ibz, spin1, wave_vk, msg) == 0, msg)
     775              : 
     776       638672 :                if (wave_vk%has_ur == WFD_STORED) then
     777       638453 :                  ptur_vk => wave_vk%ur
     778              :                else
     779          219 :                  call wfd%get_ur(iv,ik_ibz,spin1,ur_vk)
     780          219 :                  ptur_vk => ur_vk
     781              :                end if
     782              :                !
     783              :                ! Load cprj for this (v,k,s1) in the BZ.
     784              :                ! Do not care about umklapp G0 in k-q as the phase is already included.
     785       638672 :                if (Wfd%usepaw==1) then
     786        51264 :                  if (wave_vk%has_cprj == WFD_STORED) then
     787        51264 :                    ptcp_vk => wave_vk%cprj
     788              :                  else
     789            0 :                    call wfd%get_cprj(iv,ik_ibz,spin1,Cryst,Cp_tmp3,sorted=.FALSE.)
     790            0 :                    ptcp_vk => Cp_tmp3
     791              :                  end if
     792        51264 :                  call paw_symcprj_op(ik_bz,nspinor,1,Cryst,Kmesh,Pawtab,Pawang,ptcp_vk,Cp_vk)
     793              :                end if
     794              : 
     795      2773248 :                do ivp=bidx(1,3),bidx(2,3) !do ivp=BSp%lomo,BSp%homo
     796              : 
     797      1918960 :                  if (is_resonant) then
     798      1842928 :                    itp = BSp%vcks2t(ivp,icp,ikp_bz,spin2)
     799              :                  else ! have to exchange band indices
     800        76032 :                    itp = BSp%vcks2t(icp,ivp,ikp_bz,spin2)
     801              :                  end if
     802              : 
     803      1918960 :                  if (itp==0) CYCLE ! ir-uv-cutoff
     804              : 
     805              :                  ! FIXME Temporary work around, when ikp_bz == ik it might happen that itp<it
     806              :                  ! should rewrite the loops using contracted k-dependent indices for bands
     807      1918960 :                  if (itp<it) CYCLE
     808              : 
     809      1883684 :                  ir = it + itp*(itp-1)/2
     810      1883684 :                  if (ir<t_start(my_rank).or.ir>t_stop(my_rank)) CYCLE
     811              : 
     812      1877264 :                  ene_tp = BSp%Trans(itp,spin2)%en
     813              : 
     814              :                  ! ============================================
     815              :                  ! === Calculate matrix elements rhxtwg_vpv ===
     816              :                  ! ============================================
     817      1877264 :                  if (ik_bz==ikp_bz) then
     818              :                    ! Already in memory.
     819        42928 :                    rhxtwg_vpv(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,ivp,iv,ik_ibz,spin1),Gsph_c)
     820              : 
     821              :                  else
     822              : 
     823      1834336 :                    ABI_CHECK(wfd%get_wave_ptr(ivp, ikp_ibz, spin2, wave_vkp, msg) == 0, msg)
     824              : 
     825              :                    ! Calculate matrix element from wfr.
     826      1834336 :                    if (wave_vkp%has_ur == WFD_STORED) then
     827      1834123 :                      ptur_vkp => wave_vkp%ur
     828              :                    else
     829          213 :                      call wfd%get_ur(ivp,ikp_ibz,spin2,ur_vkp)
     830          213 :                      ptur_vkp => ur_vkp
     831              :                    end if
     832              :                    !
     833              :                    ! Load cprj for this (vp,kp,s2) in the BZ.
     834              :                    ! Do not care about umklapp G0 in k-q as the phase is already included.
     835      1834336 :                    if (Wfd%usepaw==1) then
     836       144640 :                      if (wave_vkp%has_cprj == WFD_STORED) then
     837       144640 :                        ptcp_vkp =>  wave_vkp%cprj
     838              :                      else
     839            0 :                        call wfd%get_cprj(ivp,ikp_ibz,spin2,Cryst,Cp_tmp4,sorted=.FALSE.)
     840            0 :                        ptcp_vkp => Cp_tmp4
     841              :                      end if
     842       144640 :                      call paw_symcprj_op(ikp_bz,nspinor,1,Cryst,Kmesh,Pawtab,Pawang,ptcp_vkp,Cp_vkp)
     843              :                    end if
     844              : 
     845              :                    call rho_tw_g(nspinor,npweps,nfftot_osc,ndat1,ngfft_osc,map2sphere,use_padfft,igfftg0,gbound,&
     846              :                      ptur_vkp,itim_kp,ktabr_kp,ph_mkpt,spinrot_kp,&
     847              :                      ptur_vk ,itim_k ,ktabr_k ,ph_mkt ,spinrot_k ,&
     848      1834336 :                      dim_rtwg,rhxtwg_vpv)
     849              : 
     850      1834336 :                    if (Wfd%usepaw==1) then ! Add PAW onsite contribution.
     851       144640 :                      call paw_rho_tw_g(cryst,Pwij_q,npweps,dim_rtwg,nspinor,Gsph_c%gvec,Cp_vkp,Cp_vk,rhxtwg_vpv)
     852              :                    end if
     853              :                  end if
     854              : 
     855              :                  ! Index in the global Hamiltonian matrix.
     856              :                  ir = it + itp*(itp-1_i8b)/2
     857              : 
     858      1877264 :                  if (ir<t_start(my_rank).or.ir>t_stop(my_rank)) then
     859            0 :                    write(msg,'(a,3(1x,i0))')" Gonna SIGFAULT, ir, t_start, t_stop ",ir,t_start(my_rank),t_stop(my_rank)
     860            0 :                    ABI_ERROR(msg)
     861              :                  end if
     862              :                  !ABI_CHECK(itp >= it,"itp < it")
     863              : 
     864      1877264 :                  if (BSp%prep_interp) then
     865              :                    ! Save a,b, c coefficients.
     866       246768 :                    aa_vpv = rhxtwg_vpv
     867       237456 :                    aa_vpv(2:) = czero
     868       246768 :                    bb_vpv1 = rhxtwg_vpv
     869       237456 :                    bb_vpv1(2:) = czero
     870       246768 :                    bb_vpv2 = vc_sqrt_qbz*rhxtwg_vpv
     871         4656 :                    bb_vpv2(1) = czero
     872              : 
     873         4656 :                    if (ik_bz == ikp_bz) then
     874              :                       ! Enforce orthogonality of the wavefunctions.
     875          624 :                       if (ivp == iv) then
     876          240 :                         aa_vpv(1) = cone
     877          240 :                         bb_vpv1(1) = cone
     878              :                       else
     879          384 :                         aa_vpv(1) = czero
     880          384 :                         bb_vpv1(1) = czero
     881              :                       end if
     882              :                    end if
     883              : 
     884       246768 :                    cc_vpv = vc_sqrt_qbz*rhxtwg_vpv
     885         4656 :                    cc_vpv(1) = czero
     886              : 
     887         4656 :                    aatmp = -faq * xdotc(npweps,aa_ctccp,1,aa_vpv,1)
     888         4656 :                    bbtmp = -faq * xdotc(npweps,bb_ctccp1,1,bb_vpv1,1)-faq*xdotc(npweps,bb_ctccp2,1,bb_vpv2,1)
     889         4656 :                    cctmp = -faq * xdotc(npweps,cc_ctccp,1,cc_vpv,1)
     890              : 
     891         4656 :                    acoeffs(ir) = aatmp
     892         4656 :                    bcoeffs(ir) = bbtmp
     893         4656 :                    ccoeffs(ir) = cctmp
     894              :                  end if
     895              : 
     896              :                  ! sum_G2 rho_c'c(G) W_qbz(G,G') rho_v'v(G')
     897     87272848 :                  rhxtwg_vpv = vc_sqrt_qbz * rhxtwg_vpv
     898      1877264 :                  http = - faq * xdotc(npweps,ctccp,1,rhxtwg_vpv,1)
     899              : 
     900              :                  ! Save result taking into account the symmetry of the matrix.
     901              :                  ! Note that the diagonal of the resonant block is not forced to be real
     902      2557632 :                  my_bsham(ir) = http
     903              : 
     904              : #ifdef DEV_MG_DEBUG_MODE
     905              :                  ttp_check(it,itp) = ttp_check(it,itp)+1
     906              : #endif
     907              :                end do !ivp
     908              :              end do !iv
     909              :            end do !icp
     910              :          end do !ic
     911              : 
     912        22740 :          ABI_FREE(gbound)
     913              : 
     914        23828 :          if (Wfd%usepaw==1.and.ik_bz/=ikp_bz) then ! Free the onsite contribution for this q.
     915         1020 :            call pawpwij_free(Pwij_q)
     916         2068 :            ABI_FREE(Pwij_q)
     917              :          end if
     918              : 
     919              :        end do ! ik_bz
     920              :      end do ! Fat loop over ikp_bz
     921              : 
     922              : #ifdef DEV_MG_DEBUG_MODE
     923              :      do itp=1,BSp%nreh(block)
     924              :        do it=1,BSp%nreh(block)
     925              :         ir = it + itp*(itp-1_i8b)/2
     926              :          if (itp>=it .and. ttp_check(it,itp) /= 1) then
     927              :            if (ir>=t_start(my_rank).and.ir<=t_stop(my_rank)) then
     928              :              write(std_out,*)"WARN: upper triangle is not 1 ",it,itp,ttp_check(it,itp)
     929              :              write(std_out,*)TRIM(repr_trans(Bsp%Trans(it ,spin1)))
     930              :              write(std_out,*)TRIM(repr_trans(Bsp%Trans(itp,spin2)))
     931              :            end if
     932              :          end if
     933              :          if (itp< it .and. ttp_check(it,itp) /= 0) then
     934              :            write(std_out,*)"WARN: then lower triangle is not 0 ",it,itp,ttp_check(it,itp)
     935              :            write(std_out,*)TRIM(repr_trans(Bsp%Trans(it ,spin1)))
     936              :            write(std_out,*)TRIM(repr_trans(Bsp%Trans(itp,spin2)))
     937              :          end if
     938              :        end do
     939              :      end do
     940              :      ierr = SUM(SUM(ttp_check,DIM=2),DIM=1)
     941              :      if (ierr/=my_hsize) then
     942              :        write(msg,'(a,2i0)')"ierr/=my_hsize",ierr,my_hsize
     943              :        ABI_ERROR(msg)
     944              :      end if
     945              :      ABI_FREE(ttp_check)
     946              : #endif
     947              : 
     948           24 :      ABI_FREE(ctccp)
     949           24 :      if(Bsp%prep_interp) then
     950            1 :        ABI_FREE(aa_ctccp)
     951            1 :        ABI_FREE(bb_ctccp1)
     952            1 :        ABI_FREE(bb_ctccp2)
     953            1 :        ABI_FREE(cc_ctccp)
     954              :      end if
     955              : 
     956           24 :      ABI_FREE(vc_sqrt_qbz)
     957           24 :      call wrtout(std_out,' Coulomb term completed')
     958              : 
     959           24 :      call timab(682,2,tsec) ! exc_build_ham(Coulomb)
     960              :    end if ! do_coulomb_term
     961              :    !
     962              :    ! =====================
     963              :    ! === Exchange term ===
     964              :    ! =====================
     965              :    ! TODO might add treatment of <psi|q+G|psi> for q+G -> 0
     966              :    ! TODO might used enlarged G-sphere for better convergence.
     967           24 :    if (do_exchange_term) then
     968              : 
     969              :      !call exc_build_v(spin1,spin2,nsppol,npweps,Bsp,Cryst,Kmesh,Qmesh,Gsph_x,Gsph_c,Vcp,&
     970              :      ! &  is_resonant,rhxtwg_q0,nproc,my_rank,t_start,t_stop,my_bsham,comm)
     971              : 
     972           24 :      call timab(683,1,tsec) ! exc_build_ham(exchange)
     973              : 
     974           24 :      write(msg,'(a,2i2,a)')" Calculating exchange term for (spin1,spin2) ",spin1,spin2," ..."
     975           24 :      call wrtout(std_out, msg)
     976              : 
     977           72 :      ABI_MALLOC(rhotwg1,(npweps))
     978           48 :      ABI_MALLOC(rhotwg2,(npweps))
     979              : 
     980           24 :      ngx = Gsph_x%ng
     981           72 :      ABI_MALLOC(vc_sqrt_qbz,(ngx))
     982              : 
     983              :      ! * Get iq_ibz, and symmetries from iq_bz.
     984           24 :      iq_bz = iqbz0 ! q = 0 -> iqbz0
     985           24 :      call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q)
     986              : 
     987              :      ! * Set up table of |q(BZ)+G|
     988           24 :      if (iq_ibz==1) then
     989         7078 :        do ig=1,ngx
     990         7054 :          ISg = Gsph_x%rottb(ig,itim_q,isym_q)
     991         7078 :          vc_sqrt_qbz(ISg)=Vcp%vcqlwl_sqrt(ig,1)
     992              :        end do
     993              :      else
     994            0 :         ABI_ERROR("iq_ibz should be 1")
     995              :      end if
     996              : 
     997         9272 :      do itp=1,BSp%nreh(block) ! Loop over transition tp = (kp,vp,cp,spin2)
     998              : 
     999         9248 :        if (itp<my_cols(1) .or. itp>my_cols(2)) CYCLE ! I dont have this column.
    1000         7716 :        ene_tp = Bsp%Trans(itp,spin2)%en
    1001         7716 :        ikp_bz = Bsp%Trans(itp,spin2)%k
    1002         7716 :        ivp    = Bsp%Trans(itp,spin2)%v
    1003         7716 :        icp    = Bsp%Trans(itp,spin2)%c
    1004              : 
    1005         7716 :        ikp_ibz = Kmesh%tab (ikp_bz)
    1006         7716 :        isym_kp = Kmesh%tabo(ikp_bz)
    1007         7716 :        itim_kp = (3-Kmesh%tabi(ikp_bz))/2
    1008              : 
    1009         7716 :        if (is_resonant) then
    1010         7332 :          rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,ivp,icp,ikp_ibz,spin2),Gsph_c)
    1011              :        else ! Code for coupling block.
    1012          384 :          rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,icp,ivp,ikp_ibz,spin2),Gsph_c)
    1013              :        end if
    1014              :        !
    1015              :        ! Multiply by the Coulomb term.
    1016       365516 :         do ig=2,npweps
    1017       365516 :           rhotwg2(ig) = rhotwg2(ig) * vc_sqrt_qbz(ig) * vc_sqrt_qbz(ig)
    1018              :         end do
    1019              : 
    1020      1886073 :        do it=1,itp ! Loop over transition t = (k,v,c,spin1)
    1021      1878333 :          ir = it + itp*(itp-1_i8b)/2
    1022      1878333 :          if (ir<t_start(my_rank) .or. ir>t_stop(my_rank)) CYCLE
    1023              : 
    1024      1877264 :          ene_t = Bsp%Trans(it,spin1)%en
    1025      1877264 :          ik_bz = Bsp%Trans(it,spin1)%k
    1026      1877264 :          iv    = Bsp%Trans(it,spin1)%v
    1027      1877264 :          ic    = Bsp%Trans(it,spin1)%c
    1028              : 
    1029      1877264 :          ik_ibz = Kmesh%tab(ik_bz)
    1030      1877264 :          isym_k = Kmesh%tabo(ik_bz)
    1031      1877264 :          itim_k = (3-Kmesh%tabi(ik_bz))/2
    1032              :          !if (itim_k==2) CYCLE ! time-reversal or not
    1033              : 
    1034      1877264 :          rhotwg1(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,iv,ic,ik_ibz,spin1),Gsph_c)
    1035              :          !
    1036              :          ! sum over G/=0
    1037      1877264 :          ctemp = xdotc(npweps-1,rhotwg1(2:),1,rhotwg2(2:),1)
    1038      1877264 :          ctemp = faq * kx_fact * ctemp
    1039              : 
    1040              :          ! exchange term is non divergent !
    1041      1877264 :          if (BSp%prep_interp) then
    1042         4656 :            ccoeffs(ir) = ccoeffs(ir) + ctemp
    1043              :          end if
    1044              : 
    1045      1887581 :          my_bsham(ir) = my_bsham(ir) + ctemp
    1046              :        end do !it
    1047              :      end do !itp
    1048              : 
    1049           24 :      ABI_FREE(rhotwg1)
    1050           24 :      ABI_FREE(rhotwg2)
    1051           24 :      ABI_FREE(vc_sqrt_qbz)
    1052              : 
    1053           24 :      call timab(683,2,tsec) ! exc_build_ham(exchange)
    1054              :    end if ! do_exchange_term
    1055              :    !
    1056              :    ! =====================
    1057              :    ! === Diagonal term ===
    1058              :    ! =====================
    1059           24 :    if (is_resonant .and. spin1==spin2) then
    1060           23 :      write(msg,'(a,2i2,a)')" Adding diagonal term for (spin1,spin2) ",spin1,spin2," ..."
    1061           23 :      call wrtout(std_out, msg)
    1062         8887 :      do it=1,BSp%nreh(block)
    1063         8864 :        ir = it + it*(it-1_i8b)/2
    1064         8887 :        if (ir>=t_start(my_rank) .and. ir<=t_stop(my_rank)) my_bsham(ir) = my_bsham(ir) + Bsp%Trans(it,spin1)%en
    1065              :      end do
    1066              :    end if
    1067              : 
    1068              :    if (.FALSE.) then
    1069              :      dump_unt = get_unit()
    1070              :      msg=' Coupling Hamiltonian matrix elements: '
    1071              :      if (is_resonant) msg=' Reasonant Hamiltonian matrix elements: '
    1072              :      call wrtout(dump_unt, msg)
    1073              :      call wrtout(dump_unt,'    k  v  c  s      k" v" c" s"       H')
    1074              :      do itp=1,BSp%nreh(block)
    1075              :        ikp_bz = Bsp%Trans(itp,spin2)%k
    1076              :        ivp    = Bsp%Trans(itp,spin2)%v
    1077              :        icp    = Bsp%Trans(itp,spin2)%c
    1078              :        do it=1,itp
    1079              :          ik_bz = Bsp%Trans(it,spin1)%k
    1080              :          iv    = Bsp%Trans(it,spin1)%v
    1081              :          ic    = Bsp%Trans(it,spin1)%c
    1082              :          ir = it + itp*(itp-1_i8b)/2
    1083              :          if (ir>=t_start(my_rank).and.ir<=t_stop(my_rank)) then
    1084              :            http = my_bsham(ir)
    1085              :            !if (ABS(http) > tol3) then
    1086              :            write(msg,'(2(i0,1x),2(i5,3i3,3x),2f7.3)')it,itp, ik_bz,iv,ic,spin1, ikp_bz,ivp,icp,spin2, http
    1087              :            call wrtout(dump_unt, msg)
    1088              :            !end if
    1089              :          end if
    1090              :        end do
    1091              :      end do
    1092              :    end if
    1093              : 
    1094              : !DBYG
    1095              :    if (.False.) then
    1096              :      dump_unt = get_unit()
    1097              :      dump_unt = 999
    1098              :      msg=' Coupling Hamiltonian matrix elements: '
    1099              :      if (is_resonant) msg=' Resonant Hamiltonian matrix elements: '
    1100              :      call wrtout(dump_unt, msg)
    1101              :      call wrtout(dump_unt,'    k v  c  s      k" v" c" s"       H')
    1102              :      do itp=1,BSp%nreh(block)
    1103              :        ikp_bz = Bsp%Trans(itp,spin2)%k
    1104              :        ivp    = Bsp%Trans(itp,spin2)%v
    1105              :        icp    = Bsp%Trans(itp,spin2)%c
    1106              :        do it=1,BSp%nreh(block)
    1107              :          ik_bz = Bsp%Trans(it,spin1)%k
    1108              :          iv    = Bsp%Trans(it,spin1)%v
    1109              :          ic    = Bsp%Trans(it,spin1)%c
    1110              :          if(it > itp) then
    1111              :            ir = itp+it*(it-1_i8b)/2
    1112              :          else
    1113              :            ir = it + itp*(itp-1_i8b)/2
    1114              :          end if
    1115              :          if (ir>=t_start(my_rank).and.ir<=t_stop(my_rank)) then
    1116              :            if(it > itp) then
    1117              :              http = CONJG(my_bsham(ir))
    1118              :              if (BSp%prep_interp) then
    1119              :                aatmp = CONJG(acoeffs(ir))
    1120              :                bbtmp = CONJG(bcoeffs(ir))
    1121              :                cctmp = CONJG(ccoeffs(ir))
    1122              :              end if
    1123              :            else
    1124              :              http = my_bsham(ir)
    1125              :              if (BSp%prep_interp) then
    1126              :                aatmp = acoeffs(ir)
    1127              :                bbtmp = bcoeffs(ir)
    1128              :                cctmp = ccoeffs(ir)
    1129              :              end if
    1130              :            end if
    1131              :            if (it == itp) http = http - Bsp%Trans(it,spin1)%en
    1132              :            !if (ABS(http) > tol3) then
    1133              :            if (BSp%prep_interp) then
    1134              :              write(msg,'(2(i0,1x),2(i5,3i3,3x),2f24.20,2f24.20,2f24.20,2f24.20)')it,itp, ik_bz,iv,ic,spin1, ikp_bz,ivp,icp,&
    1135              : &   spin2, http, aatmp, bbtmp, cctmp
    1136              :            else
    1137              :              write(msg,'(2(i0,1x),2(i5,3i3,3x),2f24.20)')it,itp, ik_bz,iv,ic,spin1, ikp_bz,ivp,icp,spin2, http
    1138              :            end if
    1139              :            call wrtout(dump_unt, msg)
    1140              :            !end if
    1141              :          end if
    1142              :        end do
    1143              :      end do
    1144              :    end if
    1145              : 
    1146           24 :    call timab(684,1,tsec) ! exc_build_ham(synchro)
    1147           24 :    call xmpi_barrier(comm)
    1148           24 :    call timab(684,2,tsec) ! exc_build_ham(synchro)
    1149              :    !
    1150              :    ! =================================
    1151              :    ! === Write Hamiltonian on disk ===
    1152              :    ! =================================
    1153           24 :    call timab(685,1,tsec) ! exc_build_ham(write_ham)
    1154           48 :    if (use_mpiio) then
    1155              : #ifdef HAVE_MPI_IO
    1156              :      ! Write the Hamiltonian with collective MPI-IO.
    1157              :      if (BSp%prep_interp) then
    1158              :        ABI_ERROR("Preparation of interpolation technique not yet coded with MPI-IO")
    1159              :      end if
    1160              :      ABI_CHECK(nsppol==1,"nsppol==2 not coded, offset is wrong")
    1161              :      !
    1162              :      old_type = MPI_DOUBLE_COMPLEX
    1163              :      call xmpio_create_fherm_packed(my_starts,my_ends,is_fortran_file,my_offset,old_type,hmat_type,offset_err)
    1164              : 
    1165              :      if (offset_err/=0) then
    1166              :        write(msg,"(3a)")&
    1167              :         "Global position index cannot be stored in a standard Fortran integer. ",ch10,&
    1168              :         "BSE matrix cannot be written with a single MPI-IO call. "
    1169              :        ABI_ERROR(msg)
    1170              :      end if
    1171              :      !
    1172              :      ! Each node uses a different offset to skip the header and the blocks written by the other CPUs.
    1173              :      my_offset = offset_of_block(block) + my_offset
    1174              : 
    1175              :      call MPI_FILE_SET_VIEW(mpi_fh, my_offset, MPI_BYTE, hmat_type, 'native', MPI_INFO_NULL, mpi_err)
    1176              :      ABI_CHECK_MPI(mpi_err,"SET_VIEW")
    1177              : 
    1178              :      call MPI_TYPE_FREE(hmat_type,mpi_err)
    1179              :      ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
    1180              : 
    1181              :      if (hsize_of(my_rank) /= INT(hsize_of(my_rank),kind=i4b) ) then
    1182              :        ABI_ERROR("Wraparound error")
    1183              :      end if
    1184              : 
    1185              :      tmp_size = INT(hsize_of(my_rank))
    1186              :      call MPI_FILE_WRITE_ALL(mpi_fh, my_bsham, tmp_size, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
    1187              :      ABI_CHECK_MPI(mpi_err,"FILE_WRITE")
    1188              : 
    1189              :      ! It seems that personal calls in make the code stuck
    1190              :      !if (is_fortran_file .and. my_rank==master) then ! Master writes the Fortran record markers.
    1191              :      ! Write the Fortran record markers.
    1192              :      neh2=BSp%nreh(block)
    1193              :      ABI_MALLOC(bsize_frecord,(neh2))
    1194              :      bsize_frecord = (/(col_glob * xmpi_bsize_dpc, col_glob=1,neh2)/)
    1195              :      ! ehdr_offset points to the end of the header.
    1196              :      !call xmpio_write_frmarkers(mpi_fh,ehdr_offset,xmpio_collective,neh2,bsize_frecord,mpi_err)
    1197              :      my_offset = offset_of_block(block)
    1198              :      call xmpio_write_frmarkers(mpi_fh,my_offset,xmpio_collective,neh2,bsize_frecord,ierr)
    1199              :      ABI_CHECK(ierr==0,"Error while writing Fortran markers")
    1200              :      ABI_FREE(bsize_frecord)
    1201              : #else
    1202              :      ABI_BUG("You should not be here!")
    1203              : #endif
    1204              :    else
    1205              :      ! Use FORTRAN IO with sequential access mode.
    1206              :      ! * Each node sends its data to master node.
    1207              :      ! * Blocks are distributed according to the rank of the node.
    1208              :      ! * Matrix is written by columns hence make sure that the last column is completely written.
    1209           24 :      call cwtime(cputime,walltime,gflops,"start")
    1210              : 
    1211           24 :      if (my_rank==master) then
    1212           20 :        prev_nrows=0; if (my_cols(2) /= my_rows(2)) prev_nrows = my_rows(2)
    1213           20 :        ncol = my_cols(2)-my_cols(1)+1
    1214           20 :        ist=1
    1215         7428 :        do jj=1,ncol
    1216         7408 :          col_glob = my_starts(2) + jj - 1
    1217         7408 :          nrows = col_glob; if (jj==ncol) nrows=my_rows(2)
    1218         7408 :          iend = ist + nrows -1
    1219         7408 :          write(bsh_unt) my_bsham(ist:iend)
    1220         7408 :          if (BSp%prep_interp) then
    1221           96 :            write(a_unt) acoeffs(ist:iend)
    1222           96 :            write(b_unt) bcoeffs(ist:iend)
    1223           96 :            write(c_unt) ccoeffs(ist:iend)
    1224              :          end if
    1225         7428 :          ist=iend+1
    1226              :        end do
    1227           20 :        write(msg,'(2(a,i0))')" Wraparound error: iend=",iend," my_hsize=",hsize_of(my_rank)
    1228           20 :        ABI_CHECK(iend == hsize_of(my_rank),msg)
    1229           20 :        ABI_FREE(my_bsham)
    1230           20 :        if (BSp%prep_interp) then
    1231            1 :          ABI_FREE(acoeffs)
    1232            1 :          ABI_FREE(bcoeffs)
    1233            1 :          ABI_FREE(ccoeffs)
    1234              :        end if
    1235              :      end if
    1236              : 
    1237           24 :      call xmpi_barrier(comm)
    1238              :      !
    1239              :      ! Collect data from the other nodes.
    1240           38 :      do sender=1,nproc-1
    1241              :        ! If I'm not involved, jump to the end of the loop and wait there (sequential IO? Of course!)
    1242           14 :        if (all(my_rank /= [sender, master])) goto 100
    1243              : 
    1244            8 :        if (my_rank==master)  then
    1245           12 :          ABI_MALLOC(buffer,(hsize_of(sender)))
    1246            4 :          if (BSp%prep_interp) then
    1247            0 :            ABI_MALLOC(abuffer,(hsize_of(sender)))
    1248            0 :            ABI_MALLOC(bbuffer,(hsize_of(sender)))
    1249            0 :            ABI_MALLOC(cbuffer,(hsize_of(sender)))
    1250              :          end if
    1251              :        end if
    1252            8 :        tmp_size = INT(hsize_of(sender),kind=i4b)
    1253            8 :        call xmpi_exch(my_bsham,tmp_size,sender,buffer,master,comm,10*block+1,mpi_err)
    1254            8 :        if (BSp%prep_interp) then
    1255            0 :          call xmpi_exch(acoeffs,tmp_size,sender,abuffer,master,comm,10*block+2,mpi_err)
    1256            0 :          call xmpi_exch(bcoeffs,tmp_size,sender,bbuffer,master,comm,10*block+3,mpi_err)
    1257            0 :          call xmpi_exch(ccoeffs,tmp_size,sender,cbuffer,master,comm,10*block+4,mpi_err)
    1258              :        end if
    1259              : 
    1260              :        ! TODO Be careful with the MPI TAG here, add optional Arguments in xmpi_exch so that the TAG can be specified!
    1261           24 :        proc_start = (/my_rows(1),my_cols(1)/)
    1262           24 :        proc_end   = (/my_rows(2),my_cols(2)/)
    1263           24 :        my_extrema(:,1) = proc_start
    1264           24 :        my_extrema(:,2) = proc_end
    1265              : 
    1266            8 :        sender_extrema = my_extrema ! just to avoid NAN on sender. xechh_mpi is not well designed
    1267            8 :        call xmpi_exch(my_extrema,4,sender,sender_extrema,master,comm,10*block+5,mpi_err)
    1268              : 
    1269            8 :        if (my_rank==master) then
    1270           12 :           proc_start = sender_extrema(:,1)
    1271           12 :           proc_end   = sender_extrema(:,2)
    1272              :           !write(std_out,*)"proc_start, proc_end",proc_start,proc_end
    1273              : 
    1274            4 :          if (prev_nrows>0) then ! backspace the file if the last record written was not complete.
    1275              :            !write(std_out,*)" master node had to call backspace"
    1276            4 :            backspace(bsh_unt)
    1277           12 :            ABI_MALLOC(prev_col,(prev_nrows))
    1278            4 :            read(bsh_unt) prev_col
    1279            4 :            backspace(bsh_unt)
    1280              : 
    1281            4 :            if (BSp%prep_interp) then
    1282            0 :              backspace(a_unt)
    1283            0 :              ABI_MALLOC(aprev_col,(prev_nrows))
    1284            0 :              read(a_unt) aprev_col
    1285            0 :              backspace(a_unt)
    1286              : 
    1287            0 :              backspace(b_unt)
    1288            0 :              ABI_MALLOC(bprev_col,(prev_nrows))
    1289            0 :              read(b_unt) bprev_col
    1290            0 :              backspace(b_unt)
    1291              : 
    1292            0 :              backspace(c_unt)
    1293            0 :              ABI_MALLOC(cprev_col,(prev_nrows))
    1294            0 :              read(c_unt) cprev_col
    1295            0 :              backspace(c_unt)
    1296              :            end if
    1297              :          end if
    1298              :          !
    1299              :          ! Write the columns owned by sender.
    1300            4 :          ncol = proc_end(2)-proc_start(2)+1
    1301            4 :          ist=1
    1302          312 :          do jj=1,ncol
    1303          308 :            col_glob = proc_start(2) + jj-1
    1304          308 :            nrows = col_glob
    1305          308 :            if (jj==1   )  nrows=col_glob - proc_start(1) + 1
    1306          308 :            if (jj==ncol) then
    1307            4 :              nrows=proc_end(1)
    1308            4 :              if (ncol==1)  nrows=proc_end(1) - proc_start(1) + 1
    1309              :            end if
    1310          308 :            iend = ist + nrows -1
    1311              :            !write(std_out,*)"Using nrows, ist, iend=",nrows,ist,iend
    1312          308 :            if (jj==1 .and. prev_nrows>0) then ! join prev_col and this subcolumn.
    1313         1073 :              write(bsh_unt) CMPLX(prev_col,kind=dp),CMPLX(buffer(ist:iend),kind=dp)
    1314            4 :              if (BSp%prep_interp) then
    1315            0 :                write(a_unt) CMPLX(aprev_col,kind=dp),CMPLX(abuffer(ist:iend),kind=dp)
    1316            0 :                write(b_unt) CMPLX(bprev_col,kind=dp),CMPLX(bbuffer(ist:iend),kind=dp)
    1317            0 :                write(c_unt) CMPLX(cprev_col,kind=dp),CMPLX(cbuffer(ist:iend),kind=dp)
    1318              :              end if
    1319            4 :              prev_nrows = prev_nrows + iend-ist+1
    1320              :            else
    1321        92149 :              write(bsh_unt) CMPLX(buffer(ist:iend),kind=dp)
    1322          304 :              if (BSp%prep_interp) then
    1323            0 :                write(a_unt) CMPLX(abuffer(ist:iend),kind=dp)
    1324            0 :                write(b_unt) CMPLX(bbuffer(ist:iend),kind=dp)
    1325            0 :                write(c_unt) CMPLX(cbuffer(ist:iend),kind=dp)
    1326              :              end if
    1327              :              prev_nrows=0
    1328              :            end if
    1329          312 :            ist=iend+1
    1330              :          end do
    1331            4 :          if (ncol>1) then ! Reset prev_nrows if a new column has begun.
    1332            4 :            prev_nrows = proc_end(1)
    1333            4 :            if (proc_end(1) == proc_end(2)) prev_nrows = 0
    1334              :          end if
    1335            4 :          if (iend/=hsize_of(sender)) then
    1336            0 :            write(msg,'(2(a,i0))')" Wraparound error: iend=",iend," my_hsize=",hsize_of(sender)
    1337            0 :            ABI_ERROR(msg)
    1338              :          end if
    1339            4 :          ABI_SFREE(prev_col)
    1340            4 :          if (BSp%prep_interp) then
    1341            0 :            ABI_SFREE(aprev_col)
    1342            0 :            ABI_SFREE(bprev_col)
    1343            0 :            ABI_SFREE(cprev_col)
    1344              :          end if
    1345            4 :          ABI_FREE(buffer)
    1346            4 :          if (BSp%prep_interp) then
    1347            0 :            ABI_FREE(abuffer)
    1348            0 :            ABI_FREE(bbuffer)
    1349            0 :            ABI_FREE(cbuffer)
    1350              :          end if
    1351              :        end if ! master
    1352              :        !
    1353           38 : 100    call xmpi_barrier(comm)
    1354              :      end do ! sender
    1355              : 
    1356           24 :      call cwtime(cputime,walltime,gflops,"stop")
    1357           24 :      write(msg,'(2(a,f9.1),a)')" Fortran-IO completed. cpu_time: ",cputime,"[s], walltime: ",walltime," [s]"
    1358           24 :      call wrtout(std_out, msg, do_flush=.True.)
    1359              :    end if ! use_mpiio
    1360           24 :    call timab(685,2,tsec) ! exc_build_ham(write_ham)
    1361              :    !
    1362           24 :    ABI_SFREE(my_bsham)
    1363           24 :    if (BSp%prep_interp) then
    1364            1 :      ABI_SFREE(acoeffs)
    1365            1 :      ABI_SFREE(bcoeffs)
    1366            1 :      ABI_SFREE(ccoeffs)
    1367              :    end if
    1368           24 :    ABI_FREE(t_start)
    1369           24 :    ABI_FREE(t_stop)
    1370           47 :    ABI_FREE(hsize_of)
    1371              :  end do ! block
    1372              :  !
    1373              :  ! ===========================================
    1374              :  ! === Exchange term for spin_up spin_down ===
    1375              :  ! ===========================================
    1376              : 
    1377           23 :  if (nsppol==2) then
    1378            1 :    call timab(686,2,tsec) ! exc_build_ham(exch.spin)
    1379            1 :    block=3
    1380            1 :    neh1=BSp%nreh(1)
    1381            1 :    neh2=BSp%nreh(2)
    1382              :    !
    1383              :    ! The oscillators at q=0 are available on each node for both spin.
    1384              :    ! Here the calculation of the block is parallelized over columns.
    1385            3 :    ABI_MALLOC(col_start,(0:nproc-1))
    1386            2 :    ABI_MALLOC(col_stop,(0:nproc-1))
    1387            1 :    call xmpi_split_work2_i4b(neh2,nproc,col_start,col_stop)
    1388              : 
    1389            1 :    my_cols(1) = col_start(my_rank)
    1390            1 :    my_cols(2) = col_stop (my_rank)
    1391            1 :    if (my_cols(2)-my_cols(1)<=0) then
    1392            0 :      ABI_ERROR("One of the processors has zero columns!")
    1393              :    end if
    1394              : 
    1395            2 :    ABI_MALLOC(ncols_of,(0:nproc-1))
    1396            2 :    ncols_of=0
    1397            2 :    do rank=0,nproc-1
    1398            2 :      if (col_stop(rank)>=col_start(rank)) ncols_of(rank) = col_stop(rank)-col_start(rank)+1
    1399              :    end do
    1400              : 
    1401            1 :    ABI_FREE(col_start)
    1402            1 :    ABI_FREE(col_stop)
    1403              :    !
    1404              :    ! TODO might add treatment of <psi|q+G|psi> for q+G -> 0
    1405              :    ! TODO might used enlarged G-sphere for better convergence.
    1406              :    ! Note that my_kxssp is always written on file when nsppol=2, even when
    1407              :    ! non-local field effects are neglected.
    1408            4 :    ABI_MALLOC(my_kxssp,(neh1,my_cols(1):my_cols(2)))
    1409       147841 :    my_kxssp=czero
    1410              : 
    1411            1 :    if (do_exchange_term) then
    1412            1 :      spin1=1; spin2=2
    1413            1 :      write(msg,'(a,2i2,a)')" Calculating exchange term for (spin1,spin2) ",spin1,spin2," ..."
    1414            1 :      call wrtout(std_out, msg)
    1415              : 
    1416            3 :      ABI_MALLOC(rhotwg1,(npweps))
    1417            2 :      ABI_MALLOC(rhotwg2,(npweps))
    1418              : 
    1419            1 :      ngx = Gsph_x%ng
    1420            3 :      ABI_MALLOC(vc_sqrt_qbz,(ngx))
    1421              :      !
    1422              :      ! * Get iq_ibz, and symmetries from iq_bz.
    1423            1 :      iq_bz = iqbz0 ! q = 0 -> iqbz0
    1424            1 :      call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q)
    1425              :      !
    1426              :      ! * Set up table of |q(BZ)+G|
    1427            1 :      if (iq_ibz==1) then
    1428          170 :        do ig=1,ngx
    1429          169 :          ISg = Gsph_x%rottb(ig,itim_q,isym_q)
    1430          170 :          vc_sqrt_qbz(ISg)=Vcp%vcqlwl_sqrt(ig,1)
    1431              :        end do
    1432              :      else
    1433            0 :         ABI_ERROR("iq_ibz should be 1")
    1434              :      end if
    1435              : 
    1436          385 :      do itp=1,neh2 ! Loop over transition tp = (kp,vp,cp,spin2)
    1437              : 
    1438          384 :        if (itp<my_cols(1) .or. itp>my_cols(2)) CYCLE ! I dont have this column.
    1439          384 :        ene_tp = Bsp%Trans(itp,spin2)%en
    1440          384 :        ikp_bz = Bsp%Trans(itp,spin2)%k
    1441          384 :        ivp    = Bsp%Trans(itp,spin2)%v
    1442          384 :        icp    = Bsp%Trans(itp,spin2)%c
    1443              : 
    1444          384 :        ikp_ibz = Kmesh%tab (ikp_bz)
    1445          384 :        isym_kp = Kmesh%tabo(ikp_bz)
    1446          384 :        itim_kp = (3-Kmesh%tabi(ikp_bz))/2
    1447              : 
    1448          384 :        if (is_resonant) then
    1449          384 :          rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,ivp,icp,ikp_ibz,spin2),Gsph_c)
    1450              :        else ! Code for coupling block.
    1451            0 :          rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,icp,ivp,ikp_ibz,spin2),Gsph_c)
    1452              :        end if
    1453              :        !
    1454              :        ! Multiply by the Coulomb term.
    1455        19584 :         do ig=2,npweps
    1456        19584 :           rhotwg2(ig) = rhotwg2(ig) * vc_sqrt_qbz(ig) * vc_sqrt_qbz(ig)
    1457              :         end do
    1458              : 
    1459       147841 :        do it=1,neh1 ! Loop over transition t = (k,v,c,spin1) FULL matrix.
    1460              : 
    1461       147456 :          ene_t = Bsp%Trans(it,spin1)%en
    1462       147456 :          ik_bz = Bsp%Trans(it,spin1)%k
    1463       147456 :          iv    = Bsp%Trans(it,spin1)%v
    1464       147456 :          ic    = Bsp%Trans(it,spin1)%c
    1465              : 
    1466       147456 :          ik_ibz = Kmesh%tab(ik_bz)
    1467       147456 :          isym_k = Kmesh%tabo(ik_bz)
    1468       147456 :          itim_k = (3-Kmesh%tabi(ik_bz))/2
    1469              :          !if (itim_k==2) CYCLE ! time-reversal or not
    1470              : 
    1471       147456 :          rhotwg1(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,iv,ic,ik_ibz,spin1),Gsph_c)
    1472              :          !
    1473              :          ! sum over G/=0
    1474       147456 :          ctemp = XDOTC(npweps-1,rhotwg1(2:),1,rhotwg2(2:),1)
    1475       147456 :          ctemp = faq * kx_fact * ctemp
    1476              : 
    1477       147840 :          my_kxssp(it,itp) = ctemp
    1478              :        end do !it
    1479              :      end do !itp
    1480              : 
    1481            1 :      ABI_FREE(rhotwg1)
    1482            1 :      ABI_FREE(rhotwg2)
    1483            1 :      ABI_FREE(vc_sqrt_qbz)
    1484              :    end if ! do_exchange_term
    1485            1 :    call timab(686,2,tsec) ! exc_build_ham(exch.spin)
    1486              :    !
    1487              :    ! =====================================
    1488              :    ! === Write the Hamiltonian on disk ===
    1489              :    ! =====================================
    1490            1 :    call timab(685,1,tsec) ! exc_build_ham(write_ham)
    1491              : 
    1492              :    if (use_mpiio) then
    1493              : #ifdef HAVE_MPI_IO
    1494              :      my_ncols=ncols_of(my_rank); old_type=MPI_DOUBLE_COMPLEX
    1495              :      call xmpio_create_fsubarray_2D((/neh1,my_ncols/),(/neh1,my_ncols/),(/1,1/),old_type,hmat_type,my_offpad,mpi_err)
    1496              :      ABI_CHECK_MPI(mpi_err,"fsubarray_2D")
    1497              :      !
    1498              :      ! Each node uses a different offset to skip the header and the blocks written by the other CPUs.
    1499              :      prev_nels=0
    1500              :      prev_ncols=0
    1501              :      if (my_rank>0) then
    1502              :        prev_ncols = SUM(ncols_of(0:my_rank-1))
    1503              :        prev_nels = neh1*prev_ncols
    1504              :      end if
    1505              :      tmp_off = prev_nels*xmpi_bsize_dpc + prev_ncols*2*xmpio_bsize_frm
    1506              : 
    1507              :      my_offset = offset_of_block(block) + tmp_off + my_offpad
    1508              : 
    1509              :      call MPI_FILE_SET_VIEW(mpi_fh, my_offset, MPI_BYTE, hmat_type, 'native', MPI_INFO_NULL, mpi_err)
    1510              :      ABI_CHECK_MPI(mpi_err,"SET_VIEW")
    1511              : 
    1512              :      call MPI_TYPE_FREE(hmat_type,mpi_err)
    1513              :      ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
    1514              : 
    1515              :      tmp_size = INT(neh1*my_ncols)
    1516              :      call MPI_FILE_WRITE_ALL(mpi_fh, my_kxssp,tmp_size, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
    1517              :      ABI_CHECK_MPI(mpi_err,"FILE_WRITE")
    1518              : 
    1519              :      ! It seems that personal calls in make the code stuck
    1520              :      ! Master writes the Fortran record markers.
    1521              :      ABI_MALLOC(bsize_frecord,(neh2))
    1522              :      bsize_frecord = neh1 * xmpi_bsize_dpc
    1523              :      ! ehdr_offset points to the end of the header.
    1524              :      !call xmpio_write_frmarkers(mpi_fh,ehdr_offset,xmpio_collective,neh2,bsize_frecord,mpi_err)
    1525              :      my_offset = offset_of_block(block)
    1526              :      call xmpio_write_frmarkers(mpi_fh,my_offset,xmpio_collective,neh2,bsize_frecord,ierr)
    1527              :      ABI_CHECK(ierr==0,"Error while writing Fortran markers")
    1528              :      ABI_FREE(bsize_frecord)
    1529              : #else
    1530              :      ABI_BUG("You should not be here")
    1531              : #endif
    1532              :    else
    1533              :      ! Use FORTRAN IO with sequential access mode.
    1534              :      ! * Each node sends its data to master node.
    1535              :      ! * Columns are distributed according to the rank of the node.
    1536            1 :      if (my_rank==master) then
    1537          385 :        do jj=my_cols(1),my_cols(2)
    1538          385 :          write(bsh_unt) my_kxssp(:,jj)
    1539              :        end do
    1540            1 :        ABI_FREE(my_kxssp)
    1541              :      end if
    1542              : 
    1543            1 :      call xmpi_barrier(comm)
    1544              :      !
    1545              :      ! Collect data from the other nodes.
    1546            1 :      do sender=1,nproc-1
    1547              :        ! If I'm not involved, jump to the end of the loop and wait there (sequential IO? Of course!)
    1548            0 :        if (all(my_rank /= [sender, master])) goto 200
    1549              : 
    1550            0 :        if (my_rank==master)  then
    1551            0 :          ABI_MALLOC(buffer_2d,(neh1,ncols_of(sender)))
    1552              :        end if
    1553            0 :        call xmpi_exch(my_kxssp,neh1*ncols_of(sender),sender,buffer_2d,master,comm,5,mpi_err)
    1554              :        !
    1555            0 :        if (my_rank==master) then ! Write the columns owned by sender.
    1556            0 :          do jj=1,ncols_of(sender)
    1557            0 :            write(bsh_unt) buffer_2d(:,jj)
    1558              :          end do
    1559            0 :          ABI_FREE(buffer_2d)
    1560              :        end if ! master
    1561              :        !
    1562            1 : 200    call xmpi_barrier(comm)
    1563              :      end do ! sender
    1564              :    end if
    1565            1 :    call timab(685,2,tsec) ! exc_build_ham(write_ham)
    1566              : 
    1567            1 :    ABI_FREE(ncols_of)
    1568            1 :    ABI_SFREE(my_kxssp)
    1569              :  end if
    1570              : 
    1571              :  ! Close the file.
    1572              :  if (use_mpiio) then
    1573              : #ifdef HAVE_MPI_IO
    1574              :    call MPI_FILE_CLOSE(mpi_fh, mpi_err)
    1575              :    ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
    1576              :    ABI_FREE(offset_of_block)
    1577              : #endif
    1578              :  end if
    1579              : 
    1580              :  ! master closes the Fortran files.
    1581           23 :  if (my_rank==master) then
    1582           19 :    close(bsh_unt)
    1583           19 :    if (BSp%prep_interp) then
    1584            1 :      close(a_unt)
    1585            1 :      close(b_unt)
    1586            1 :      close(c_unt)
    1587              :    end if
    1588              :  end if
    1589              : 
    1590              :  ! Free memory.
    1591           23 :  ABI_FREE(igfftg0)
    1592           23 :  ABI_FREE(ktabr_k)
    1593           23 :  ABI_FREE(id_tab)
    1594           23 :  ABI_FREE(ktabr_kp)
    1595           23 :  ABI_FREE(rhxtwg_vpv)
    1596           23 :  ABI_FREE(rhxtwg_cpc)
    1597           23 :  if (BSp%prep_interp) then
    1598            1 :    ABI_FREE(aa_vpv)
    1599            1 :    ABI_FREE(bb_vpv1)
    1600            1 :    ABI_FREE(bb_vpv2)
    1601            1 :    ABI_FREE(cc_vpv)
    1602            1 :    ABI_FREE(aa_cpc)
    1603            1 :    ABI_FREE(bb_cpc1)
    1604            1 :    ABI_FREE(bb_cpc2)
    1605            1 :    ABI_FREE(cc_cpc)
    1606              :  end if
    1607           23 :  ABI_FREE(ur_ckp)
    1608           23 :  ABI_FREE(ur_vkp)
    1609           23 :  ABI_FREE(ur_vk)
    1610           23 :  ABI_FREE(ur_ck)
    1611              : 
    1612              :  ! Deallocation for PAW.
    1613           23 :  if (Wfd%usepaw==1) then
    1614            2 :    call pawcprj_free(Cp_vk)
    1615            6 :    ABI_FREE(Cp_vk)
    1616            2 :    call pawcprj_free(Cp_ck)
    1617            6 :    ABI_FREE(Cp_ck)
    1618            2 :    call pawcprj_free(Cp_ckp)
    1619            6 :    ABI_FREE(Cp_ckp)
    1620            2 :    call pawcprj_free(Cp_vkp)
    1621            6 :    ABI_FREE(Cp_vkp)
    1622            2 :    call pawcprj_free(Cp_tmp1)
    1623            6 :    ABI_FREE(Cp_tmp1)
    1624            2 :    call pawcprj_free(Cp_tmp2)
    1625            6 :    ABI_FREE(Cp_tmp2)
    1626            2 :    call pawcprj_free(Cp_tmp3)
    1627            6 :    ABI_FREE(Cp_tmp3)
    1628            2 :    call pawcprj_free(Cp_tmp4)
    1629            6 :    ABI_FREE(Cp_tmp4)
    1630              :  end if
    1631              : 
    1632           23 :  call xmpi_barrier(comm)
    1633              : 
    1634              :  DBG_EXIT("COLL")
    1635              : 
    1636           23 :  call timab(680,2,tsec)
    1637              : 
    1638           46 : end subroutine exc_build_block
    1639              : !!***
    1640              : 
    1641              : !!****f* m_exc_build/exc_build_v
    1642              : !! NAME
    1643              : !!  exc_build_v
    1644              : !!
    1645              : !! FUNCTION
    1646              : !!  Calculate and write the excitonic Hamiltonian on an external binary file (Fortran file open
    1647              : !!  in random mode) for subsequent treatment in the Bethe-Salpeter code.
    1648              : !!
    1649              : !! INPUTS
    1650              : !!  BSp<excparam>=The parameters for the Bethe-Salpeter calculation.
    1651              : !!  Cryst<crystal_t>=Info on the crystalline structure.
    1652              : !!  Kmesh<kmesh_t>=The list of k-points in the BZ, IBZ and symmetry tables.
    1653              : !!  Qmesh<kmesh_t>=The list of q-points for epsilon^{-1} and related symmetry tables.
    1654              : !!  Gsph_x<gsphere_t>=Info on the G-sphere used to describe wavefunctions and W (the largest one is actually stored).
    1655              : !!  Gsph_c<gsphere_t>=Info on the G-sphere used to describe the correlation part.
    1656              : !!  Vcp<vcoul_t>=The Coulomb interaction in reciprocal space. A cutoff can be used
    1657              : !!  rhxtwg_q0
    1658              : !!  is_resonant
    1659              : !!  comm=MPI communicator.
    1660              : !!
    1661              : !! OUTPUT
    1662              : !!
    1663              : !! NOTES
    1664              : !!  *) Version for K_V = K_C (q=0), thus KP_V = KP_C
    1665              : !!  *) No exchange limit: use DFT energies in case.
    1666              : !!  *) Symmetry of H(-k-k') = H*(k k') not used.
    1667              : !!  *) Coulomb term can be approximated as diagonal in G.
    1668              : !!  *) Valence bands treated from lomo on.
    1669              : !!  *) Symmetries of the sub-blocks are used to reduce the number of elements to calculate.
    1670              : !!
    1671              : !!            ____________
    1672              : !!           |_(cv)__(vc)_|
    1673              : !!   H_exc = |  R      C  |
    1674              : !!           | -C*    -R* |
    1675              : !!
    1676              : !!   where C is symmetric and R is Hermitian provided that the QP energies are real.
    1677              : !!
    1678              : !!  For nsppol=1 ==> R = diag-W+2v; C = -W+2v
    1679              : !!  since the Hamiltonian can be diagonalized in the spin-singlet basis set thanks to
    1680              : !!  the fact that spin triplet does not contribute to the optical limit of epsilon.
    1681              : !!
    1682              : !!  For nsppol=2 ==> R = diag-W+v; C = -W+v
    1683              : !!  Now the matrix elements depend on the spin of the transitions but only those
    1684              : !!  transitions in which the spin of the electron and of the hole are equal contribute
    1685              : !!  to the macroscopic dielectric function. Moreover only the exchange term can connect transitions of different spin.
    1686              : !!  When nsppol==2 the transitions are ordered using | (cv up) | (cv dwn) | (vc up) | (vc down) |
    1687              : !!
    1688              : !!  The resonant block is given by:
    1689              : !!
    1690              : !!      |  (v'c' up)       | (v'c' dwn)   |
    1691              : !!      -----------------------------------           where v_{-+} = v_{+-}^H when the momentum of the photon is neglected.
    1692              : !!      | [diag-W+v]++     |      v+-     | (vc up)   Note that v_{+-} is not Hermitian due to the presence of different spins.
    1693              : !!  R = -----------------------------------           Actually it reduces to a Hermitian matrix when the system is not spin polarized.
    1694              : !!      |     v-+          | [diag-W+v]-- | (vc dwn)  but in this case one should use nsppol=1.
    1695              : !!      -----------------------------------           As a consequence the entire matrix is calculated and stored on file.
    1696              : !!
    1697              : !!  The coupling block is given by:
    1698              : !!
    1699              : !!      |  (c'v' up)   |    (c'v dwn)     |
    1700              : !!      -----------------------------------           where v_{-+} = v_{+-}^t when the momentum of the photon is neglected.
    1701              : !!      | [-W+v]++     |      v+-         | (vc up)   Also in this case the entire matrix v_{+-} has to be calculated
    1702              : !!  C = -----------------------------------           and stored on file.
    1703              : !!      |     v-+      |    [-W+v]--      | (vc dwn)
    1704              : !!      -----------------------------------
    1705              : !!
    1706              : !! SOURCE
    1707              : 
    1708              : subroutine exc_build_v(spin1,spin2,nsppol,npweps,Bsp,Cryst,Kmesh,Qmesh,Gsph_x,Gsph_c,Vcp,&
    1709              : &  is_resonant,rhxtwg_q0,nproc,my_rank,t_start,t_stop,my_bsham)
    1710              : 
    1711              : !Arguments ------------------------------------
    1712              : !scalars
    1713              :  integer,intent(in) :: spin1,spin2,nsppol,npweps,nproc,my_rank
    1714              :  logical,intent(in) :: is_resonant
    1715              :  type(excparam),intent(in) :: BSp
    1716              :  type(kmesh_t),intent(in) :: Kmesh,Qmesh
    1717              :  type(crystal_t),intent(in) :: Cryst
    1718              :  type(vcoul_t),intent(in) :: Vcp
    1719              :  type(gsphere_t),intent(in) :: Gsph_x,Gsph_c
    1720              : !arrays
    1721              :  integer(i8b),intent(in) :: t_start(0:nproc-1),t_stop(0:nproc-1)
    1722              :  complex(gwp),intent(in) :: rhxtwg_q0(npweps,BSp%lomo_min:BSp%humo_max,BSp%lomo_min:BSp%humo_max,Kmesh%nibz,nsppol)
    1723              :  complex(dp),intent(inout) :: my_bsham(t_start(my_rank):t_stop(my_rank))
    1724              : 
    1725              : !Local variables ------------------------------
    1726              : !scalars
    1727              :  integer :: ISg,ngx,ik_bz,ikp_bz,dim_rtwg
    1728              :  integer :: neh1,neh2,ig,nblocks
    1729              :  integer :: ik_ibz,itim_k,ikp_ibz,itim_kp,isym_k,isym_kp
    1730              :  integer :: iq_bz,iq_ibz,isym_q,itim_q,iqbz0,rank
    1731              :  integer :: iv,ivp,ic,icp
    1732              :  integer :: block
    1733              :  integer(i8b) :: tot_nels,ir,it,itp
    1734              :  real(dp) :: faq,kx_fact
    1735              :  complex(sp) :: ctemp
    1736              :  character(len=500) :: msg
    1737              : !arrays
    1738              :  integer :: bidx(2,4),spin_ids(2,3), my_cols(2),my_rows(2) !,proc_end(2),proc_start(2)
    1739              :  integer(i8b) :: nels_block(3)
    1740              :  integer,allocatable :: ncols_of(:), col_start(:),col_stop(:)
    1741              :  real(dp) :: qbz(3),tsec(2) !kbz(3),kpbz(3),
    1742              :  complex(dp),allocatable :: my_kxssp(:,:)
    1743              :  complex(gwp),allocatable :: vc_sqrt_qbz(:),rhotwg1(:),rhotwg2(:)
    1744              : !************************************************************************
    1745              : 
    1746              :  DBG_ENTER("COLL")
    1747              : 
    1748              :  write(msg,'(a,2i2,a)')" Calculating exchange term for (spin1,spin2) ",spin1,spin2," ..."
    1749              :  call wrtout(std_out, msg)
    1750              : 
    1751              :  ! Basic constants.
    1752              :  dim_rtwg=1; faq = one/(Cryst%ucvol*Kmesh%nbz)
    1753              : 
    1754              :  ! Identify the index of q==0
    1755              :  iqbz0=0
    1756              :  do iq_bz=1,Qmesh%nbz
    1757              :    if (ALL(ABS(Qmesh%bz(:,iq_bz))<tol3)) iqbz0 = iq_bz
    1758              :  end do
    1759              :  ABI_CHECK(iqbz0/=0,"q=0 not found")
    1760              :  !
    1761              :  ! Treat the spin polarization.
    1762              :  spin_ids(:,1) = (/1,1/)
    1763              :  spin_ids(:,2) = (/2,2/)
    1764              :  spin_ids(:,3) = (/1,2/)
    1765              : 
    1766              :  nblocks=1
    1767              :  kx_fact=two
    1768              :  nels_block(:)=0
    1769              :  nels_block(1)=BSp%nreh(1)*(BSp%nreh(1)+1_i8b)/2
    1770              :  tot_nels=nels_block(1)
    1771              : 
    1772              :  if (nsppol==2) then
    1773              :    nblocks=3
    1774              :    kx_fact=one
    1775              :    nels_block(1) = BSp%nreh(1)*(BSp%nreh(1)+1_i8b)/2   ! Only the upper triangle for block 1 and 2
    1776              :    nels_block(2) = BSp%nreh(2)*(BSp%nreh(2)+1_i8b)/2
    1777              :    nels_block(3) = BSp%nreh(1)*BSp%nreh(2)*1_i8b       ! Note: Block 3 does not have symmetries.
    1778              :    tot_nels= SUM(nels_block)
    1779              :  end if
    1780              :  !
    1781              :  ! Distribute the calculation of the matrix elements among the nodes.
    1782              :  ! * tstart and t_stop give the initial and final transition index treated by each node.
    1783              :  ! * my_hsize is the number of transitions treated by this processor
    1784              :  ! * my_cols(1:2) gives the initial and final column treated by this node.
    1785              :  !
    1786              :  do block=1,nsppol
    1787              :    !
    1788              :    ! Indices used to loop over bands.
    1789              :    ! bidx contains the starting and final indices used to loop over bands.
    1790              :    !
    1791              :    !      (b3,b4)
    1792              :    !         |... ...|
    1793              :    ! (b1,b2) |... ...|
    1794              :    !
    1795              :    ! Resonant matrix is given by
    1796              :    !      (v',c')
    1797              :    !       |... ...|
    1798              :    ! (v,c) |... ...|
    1799              :    !
    1800              :    ! Coupling matrix is given by
    1801              :    !       (c',v')
    1802              :    !       |... ...|
    1803              :    ! (v,c) |... ...|
    1804              : 
    1805              :    if (is_resonant) then
    1806              :      bidx(:,1) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b1
    1807              :      bidx(:,2) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b2
    1808              :      bidx(:,3) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b3
    1809              :      bidx(:,4) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b4
    1810              :    else
    1811              :      bidx(:,1) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b1
    1812              :      bidx(:,2) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b2
    1813              :      bidx(:,3) = [BSp%lumo_spin(block),BSp%humo_spin(block)] ! range for b3
    1814              :      bidx(:,4) = [BSp%lomo_spin(block),BSp%homo_spin(block)] ! range for b4
    1815              :    end if
    1816              : 
    1817              :    !spin1 = spin_ids(1,block)
    1818              :    !spin2 = spin_ids(2,block)
    1819              : 
    1820              :    my_cols=0
    1821              :    do itp=1,Bsp%nreh(block)
    1822              :      do it=1,itp
    1823              :        ir = it + itp*(itp-1_i8b)/2
    1824              :        if (ir==t_start(my_rank)) then
    1825              :          my_rows(1) = it
    1826              :          my_cols(1) = itp
    1827              :        end if
    1828              :        if (ir==t_stop(my_rank)) then
    1829              :          my_rows(2) = it
    1830              :          my_cols(2) = itp
    1831              :        end if
    1832              :      end do
    1833              :    end do
    1834              : 
    1835              :    ! Allocate big (scalable) buffer to store the BS matrix on this node.
    1836              :    !ABI_MALLOC(my_bsham,(t_start(my_rank):t_stop(my_rank)))
    1837              :    !
    1838              :    ! =====================
    1839              :    ! === Exchange term ===
    1840              :    ! =====================
    1841              :    ! TODO might add treatment of <psi|q+G|psi> for q+G -> 0
    1842              :    ! TODO might used enlarged G-sphere for better convergence.
    1843              : !if (do_exchange_term) then
    1844              :    call timab(683,1,tsec) ! exc_build_ham(exchange)
    1845              : 
    1846              :    ABI_MALLOC(rhotwg1,(npweps))
    1847              :    ABI_MALLOC(rhotwg2,(npweps))
    1848              : 
    1849              :    ngx = Gsph_x%ng
    1850              :    ABI_MALLOC(vc_sqrt_qbz,(ngx))
    1851              : 
    1852              :    ! * Get iq_ibz, and symmetries from iq_bz.
    1853              :    iq_bz = iqbz0 ! q = 0 -> iqbz0
    1854              :    call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q)
    1855              : 
    1856              :    ! * Set up table of |q(BZ)+G|
    1857              :    if (iq_ibz==1) then
    1858              :      do ig=1,ngx
    1859              :        ISg = Gsph_x%rottb(ig,itim_q,isym_q)
    1860              :        vc_sqrt_qbz(ISg)=Vcp%vcqlwl_sqrt(ig,1)
    1861              :      end do
    1862              :    else
    1863              :       ABI_ERROR("iq_ibz should be 1")
    1864              :    end if
    1865              : 
    1866              :    do itp=1,BSp%nreh(block) ! Loop over transition tp = (kp,vp,cp,spin2)
    1867              : 
    1868              :      if (itp<my_cols(1) .or. itp>my_cols(2)) CYCLE ! I dont have this column.
    1869              :      ikp_bz = Bsp%Trans(itp,spin2)%k
    1870              :      ivp    = Bsp%Trans(itp,spin2)%v
    1871              :      icp    = Bsp%Trans(itp,spin2)%c
    1872              : 
    1873              :      ikp_ibz = Kmesh%tab (ikp_bz)
    1874              :      isym_kp = Kmesh%tabo(ikp_bz)
    1875              :      itim_kp = (3-Kmesh%tabi(ikp_bz))/2
    1876              : 
    1877              :      if (is_resonant) then
    1878              :        rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,ivp,icp,ikp_ibz,spin2),Gsph_c)
    1879              :      else ! Code for coupling block.
    1880              :        rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,icp,ivp,ikp_ibz,spin2),Gsph_c)
    1881              :      end if
    1882              :      !
    1883              :      ! Multiply by the Coulomb term.
    1884              :       do ig=2,npweps
    1885              :         rhotwg2(ig) = rhotwg2(ig) * vc_sqrt_qbz(ig) * vc_sqrt_qbz(ig)
    1886              :       end do
    1887              : 
    1888              :      do it=1,itp ! Loop over transition t = (k,v,c,spin1)
    1889              :        ir = it + itp*(itp-1_i8b)/2
    1890              :        if (ir<t_start(my_rank) .or. ir>t_stop(my_rank)) CYCLE
    1891              : 
    1892              :        ik_bz   = Bsp%Trans(it,spin1)%k
    1893              :        iv      = Bsp%Trans(it,spin1)%v
    1894              :        ic      = Bsp%Trans(it,spin1)%c
    1895              : 
    1896              :        ik_ibz = Kmesh%tab(ik_bz)
    1897              :        isym_k = Kmesh%tabo(ik_bz)
    1898              :        itim_k = (3-Kmesh%tabi(ik_bz))/2
    1899              :        !if (itim_k==2) CYCLE ! time-reversal or not
    1900              : 
    1901              :        rhotwg1(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,iv,ic,ik_ibz,spin1),Gsph_c)
    1902              :        !
    1903              :        ! sum over G/=0
    1904              :        ctemp = xdotc(npweps-1,rhotwg1(2:),1,rhotwg2(2:),1)
    1905              :        ctemp = faq * kx_fact * ctemp
    1906              : 
    1907              :        ! exchange term is non divergent !
    1908              :        !if (BSp%prep_interp) then
    1909              :        !  ccoeffs(ir) = ccoeffs(ir) + ctemp
    1910              :        !end if
    1911              : 
    1912              :        my_bsham(ir) = my_bsham(ir) + ctemp
    1913              :      end do !it
    1914              :    end do !itp
    1915              : 
    1916              :    ABI_FREE(rhotwg1)
    1917              :    ABI_FREE(rhotwg2)
    1918              :    ABI_FREE(vc_sqrt_qbz)
    1919              : 
    1920              :    call timab(683,2,tsec) ! exc_build_ham(exchange)
    1921              : !end if ! do_exchange_term
    1922              :  end do ! block
    1923              : 
    1924              :  !
    1925              :  ! ===========================================
    1926              :  ! === Exchange term for spin_up spin_down ===
    1927              :  ! ===========================================
    1928              : 
    1929              : if (nsppol==2) then
    1930              :  call timab(686,2,tsec) ! exc_build_ham(exch.spin)
    1931              :  block=3
    1932              :  neh1=BSp%nreh(1)
    1933              :  neh2=BSp%nreh(2)
    1934              :  !
    1935              :  ! The oscillators at q=0 are available on each node for both spin.
    1936              :  ! Here the calculation of the block is parallelized over columns.
    1937              :  ABI_MALLOC(col_start,(0:nproc-1))
    1938              :  ABI_MALLOC(col_stop,(0:nproc-1))
    1939              :  call xmpi_split_work2_i4b(neh2,nproc,col_start,col_stop) !check this but it should be OK.
    1940              : 
    1941              :  my_cols(1) = col_start(my_rank)
    1942              :  my_cols(2) = col_stop (my_rank)
    1943              :  if (my_cols(2)-my_cols(1)<=0) then
    1944              :    ABI_ERROR("One of the processors has zero columns!")
    1945              :  end if
    1946              : 
    1947              :  ABI_MALLOC(ncols_of,(0:nproc-1))
    1948              :  ncols_of=0
    1949              :  do rank=0,nproc-1
    1950              :    if (col_stop(rank)>=col_start(rank)) ncols_of(rank) = col_stop(rank)-col_start(rank)+1
    1951              :  end do
    1952              : 
    1953              :  ABI_FREE(col_start)
    1954              :  ABI_FREE(col_stop)
    1955              :  !
    1956              :  ! TODO might add treatment of <psi|q+G|psi> for q+G -> 0
    1957              :  ! TODO might used enlarged G-sphere for better convergence.
    1958              :  ! Note that my_kxssp is always written on file when nsppol=2, even when
    1959              :  ! non-local field effects are neglected.
    1960              :  ABI_MALLOC(my_kxssp,(neh1,my_cols(1):my_cols(2)))
    1961              :  my_kxssp=czero
    1962              : 
    1963              :  !if (do_exchange_term) then
    1964              :    !spin1=1; spin2=2
    1965              :    ABI_MALLOC(rhotwg1,(npweps))
    1966              :    ABI_MALLOC(rhotwg2,(npweps))
    1967              : 
    1968              :    ngx = Gsph_x%ng
    1969              :    ABI_MALLOC(vc_sqrt_qbz,(ngx))
    1970              :    !
    1971              :    ! * Get iq_ibz, and symmetries from iq_bz.
    1972              :    iq_bz = iqbz0 ! q = 0 -> iqbz0
    1973              :    call qmesh%get_BZ_item(iq_bz,qbz,iq_ibz,isym_q,itim_q)
    1974              :    !
    1975              :    ! * Set up table of |q(BZ)+G|
    1976              :    if (iq_ibz==1) then
    1977              :      do ig=1,ngx
    1978              :        ISg = Gsph_x%rottb(ig,itim_q,isym_q)
    1979              :        vc_sqrt_qbz(ISg)=Vcp%vcqlwl_sqrt(ig,1)
    1980              :      end do
    1981              :    else
    1982              :       ABI_ERROR("iq_ibz should be 1")
    1983              :    end if
    1984              : 
    1985              :    do itp=1,neh2 ! Loop over transition tp = (kp,vp,cp,spin2)
    1986              : 
    1987              :      if (itp<my_cols(1) .or. itp>my_cols(2)) CYCLE ! I dont have this column.
    1988              :      ikp_bz = Bsp%Trans(itp,spin2)%k
    1989              :      ivp    = Bsp%Trans(itp,spin2)%v
    1990              :      icp    = Bsp%Trans(itp,spin2)%c
    1991              : 
    1992              :      ikp_ibz = Kmesh%tab (ikp_bz)
    1993              :      isym_kp = Kmesh%tabo(ikp_bz)
    1994              :      itim_kp = (3-Kmesh%tabi(ikp_bz))/2
    1995              : 
    1996              :      if (is_resonant) then
    1997              :        rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,ivp,icp,ikp_ibz,spin2),Gsph_c)
    1998              :      else ! Code for coupling block.
    1999              :        rhotwg2(:) = sym_rhotwgq0(itim_kp,isym_kp,dim_rtwg,npweps,rhxtwg_q0(:,icp,ivp,ikp_ibz,spin2),Gsph_c)
    2000              :      end if
    2001              :      !
    2002              :      ! Multiply by the Coulomb term.
    2003              :       do ig=2,npweps
    2004              :         rhotwg2(ig) = rhotwg2(ig) * vc_sqrt_qbz(ig) * vc_sqrt_qbz(ig)
    2005              :       end do
    2006              : 
    2007              :      do it=1,neh1 ! Loop over transition t = (k,v,c,spin1) FULL matrix.
    2008              :        ik_bz = Bsp%Trans(it,spin1)%k
    2009              :        iv    = Bsp%Trans(it,spin1)%v
    2010              :        ic    = Bsp%Trans(it,spin1)%c
    2011              : 
    2012              :        ik_ibz = Kmesh%tab(ik_bz)
    2013              :        isym_k = Kmesh%tabo(ik_bz)
    2014              :        itim_k = (3-Kmesh%tabi(ik_bz))/2
    2015              :        !if (itim_k==2) CYCLE ! time-reversal or not
    2016              : 
    2017              :        rhotwg1(:) = sym_rhotwgq0(itim_k,isym_k,dim_rtwg,npweps,rhxtwg_q0(:,iv,ic,ik_ibz,spin1),Gsph_c)
    2018              :        !
    2019              :        ! sum over G/=0
    2020              :        ctemp = XDOTC(npweps-1,rhotwg1(2:),1,rhotwg2(2:),1)
    2021              :        ctemp = faq * kx_fact * ctemp
    2022              : 
    2023              :        my_kxssp(it,itp) = ctemp
    2024              :      end do !it
    2025              :    end do !itp
    2026              : 
    2027              :    ABI_FREE(rhotwg1)
    2028              :    ABI_FREE(rhotwg2)
    2029              :    ABI_FREE(vc_sqrt_qbz)
    2030              :  !end if ! do_exchange_term
    2031              :  call timab(686,2,tsec) ! exc_build_ham(exch.spin)
    2032              : 
    2033              :  ABI_FREE(ncols_of)
    2034              :  ABI_SFREE(my_kxssp)
    2035              :  end if
    2036              : 
    2037              :  DBG_EXIT("COLL")
    2038              : 
    2039              : end subroutine exc_build_v
    2040              : !!***
    2041              : 
    2042              : !!****f* m_exc_build/exc_build_ham
    2043              : !! NAME
    2044              : !!  exc_build_ham
    2045              : !!
    2046              : !! FUNCTION
    2047              : !!  Calculate and write the excitonic Hamiltonian on an external binary file (Fortran binary file)
    2048              : !!  for subsequent treatment in the Bethe-Salpeter code.
    2049              : !!
    2050              : !! INPUTS
    2051              : !!  BSp<excparam>=The parameters for the Bethe-Salpeter calculation.
    2052              : !!  BS_files<excfiles>=File names internally used in the BS code.
    2053              : !!  Cryst<crystal_t>=Info on the crystalline structure.
    2054              : !!  Kmesh<kmesh_t>=The list of k-points in the BZ, IBZ and symmetry tables.
    2055              : !!  Qmesh<kmesh_t>=The list of q-points for epsilon^{-1} and related symmetry tables.
    2056              : !!  ktabr(nfftot_osc,BSp%nkbz)=The FFT index of $(R^{-1}(r-\tau))$ where R is symmetry needed to obtains
    2057              : !!    the k-points from the irreducible image.  Used to symmetrize u_Sk where S = \transpose R^{-1}
    2058              : !!  Gsph_x<gsphere_t>=Info on the G-sphere used to describe wavefunctions and W (the largest one is actually stored).
    2059              : !!  Gsph_c<gsphere_t>=Info on the G-sphere used to describe the correlation part.
    2060              : !!  Vcp<vcoul_t>=The Coulomb interaction in reciprocal space. A cutoff can be used
    2061              : !!  screen<screen_t>=Data type gathering info and data for W.
    2062              : !!  nfftot_osc=Total Number of FFT points used for the oscillator matrix elements.
    2063              : !!  ngfft_osc(18)=Info on the FFT algorithm used to calculate the oscillator matrix elements.
    2064              : !!  Psps<Pseudopotential_type>=Variables related to pseudopotentials
    2065              : !!  Pawtab(Psps%ntypat)<pawtab_type>=PAW tabulated starting data.
    2066              : !!  Pawang<pawang_type>=PAW angular mesh and related data.
    2067              : !!  Paw_pwff(Cryst%ntypat*Wfd%usepaw)<pawpwff_t>=Form factor used to calculate the onsite mat. elements of a plane wave.
    2068              : !!  Wfd<wfdgw_t>=Handler for the wavefunctions.
    2069              : !!
    2070              : !! OUTPUT
    2071              : !!  The excitonic Hamiltonian is saved on an external binary file (see below).
    2072              : !!
    2073              : !! SOURCE
    2074              : 
    2075           29 : subroutine exc_build_ham(BSp,BS_files,Cryst,Kmesh,Qmesh,ktabr,Gsph_x,Gsph_c,Vcp,&
    2076           29 :                          Wfd,screen,Hdr_bse,nfftot_osc,ngfft_osc,Psps,Pawtab,Pawang,Paw_pwff)
    2077              : 
    2078              : !Arguments ------------------------------------
    2079              : !scalars
    2080              :  integer,intent(in) :: nfftot_osc
    2081              :  type(excparam),intent(in) :: BSp
    2082              :  type(excfiles),intent(in) :: BS_files
    2083              :  type(screen_t),intent(inout) :: screen
    2084              :  type(kmesh_t),intent(in) :: Kmesh,Qmesh
    2085              :  type(crystal_t),intent(in) :: Cryst
    2086              :  type(vcoul_t),intent(in) :: Vcp
    2087              :  type(gsphere_t),intent(in) :: Gsph_x,Gsph_c
    2088              :  type(Pseudopotential_type),intent(in) :: Psps
    2089              :  type(Hdr_type),intent(inout) :: Hdr_bse
    2090              :  type(pawang_type),intent(in) :: Pawang
    2091              :  type(wfdgw_t),target,intent(inout) :: Wfd
    2092              : !arrays
    2093              :  integer,intent(in) :: ngfft_osc(18)
    2094              :  integer,intent(in) :: ktabr(nfftot_osc,Kmesh%nbz)
    2095              :  type(Pawtab_type),intent(in) :: Pawtab(Psps%ntypat*Wfd%usepaw)
    2096              :  type(pawpwff_t),intent(in) :: Paw_pwff(Psps%ntypat*Wfd%usepaw)
    2097              : 
    2098              : !Local variables ------------------------------
    2099              : !scalars
    2100              :  logical :: do_resonant,do_coupling
    2101              :  !character(len=500) :: msg
    2102              : !arrays
    2103              :  real(dp) :: tsec(2)
    2104           29 :  complex(gwp),allocatable :: all_mgq0(:,:,:,:,:)
    2105              : !************************************************************************
    2106              : 
    2107           29 :  call timab(670,1,tsec)
    2108              : 
    2109           29 :  ABI_CHECK(Wfd%nspinor==1,"nspinor==2 not coded")
    2110          116 :  ABI_CHECK(nfftot_osc==PRODUCT(ngfft_osc(1:3)),"mismatch in FFT size")
    2111              : 
    2112           29 :  if (BSp%have_complex_ene) then
    2113            0 :    ABI_ERROR("Complex energies are not supported yet")
    2114              :  end if
    2115              : 
    2116              :  ! Do we have to compute some block?
    2117           29 :  do_resonant = (BS_files%in_hreso == BSE_NOFILE)
    2118           29 :  do_coupling = (BS_files%in_hcoup == BSE_NOFILE)
    2119              : 
    2120           29 :  if (BSp%use_coupling == 0) then
    2121           28 :    if (.not.do_resonant) then
    2122            6 :      call wrtout(std_out,"Will skip the calculation of resonant block (will use BSR file)")
    2123            6 :      goto 100
    2124              :    end if
    2125              :  else
    2126            1 :    if (.not. do_resonant .and. .not. do_coupling) then
    2127            0 :      call wrtout(std_out,"Will skip the calculation of both resonant and coupling block (will use BSR and BSC files)")
    2128            0 :      goto 100
    2129              :    end if
    2130              :  end if
    2131              : 
    2132              :  ! Compute M_{k,q=0}^{b,b}(G) for all k-points in the IBZ and each pair b, b'
    2133              :  ! used for the exchange part and part of the Coulomb term.
    2134           23 :  call wrtout(std_out," Calculating all matrix elements for q=0 to save CPU time")
    2135              : 
    2136              :  call wfd_all_mgq0(Wfd,Cryst,Qmesh,Gsph_x,Vcp,Psps,Pawtab,Paw_pwff,&
    2137           23 :                    Bsp%lomo_spin,Bsp%homo_spin,Bsp%humo_spin,nfftot_osc,ngfft_osc,Bsp%npweps,all_mgq0)
    2138              : 
    2139              :  ! ========================
    2140              :  ! ==== Resonant Block ====
    2141              :  ! ========================
    2142           23 :  if (do_resonant) then
    2143           22 :    call timab(672,1,tsec)
    2144              :    call exc_build_block(BSp,Cryst,Kmesh,Qmesh,ktabr,Gsph_x,Gsph_c,Vcp,&
    2145           22 :                         Wfd,screen,Hdr_bse,nfftot_osc,ngfft_osc,Psps,Pawtab,Pawang,Paw_pwff,all_mgq0,.TRUE.,BS_files%out_hreso)
    2146           22 :    call timab(672,2,tsec)
    2147              :  end if
    2148              : 
    2149              :  ! ========================
    2150              :  ! ==== Coupling Block ====
    2151              :  ! ========================
    2152           23 :  if (do_coupling .and. BSp%use_coupling > 0) then
    2153            1 :    call timab(673,1,tsec)
    2154              :    call exc_build_block(BSp,Cryst,Kmesh,Qmesh,ktabr,Gsph_x,Gsph_c,Vcp,&
    2155            1 :                         Wfd,screen,Hdr_bse,nfftot_osc,ngfft_osc,Psps,Pawtab,Pawang,Paw_pwff,all_mgq0,.FALSE.,BS_files%out_hcoup)
    2156            1 :    call timab(673,2,tsec)
    2157              :  end if
    2158              : 
    2159              :  ! Free memory.
    2160           23 :  ABI_FREE(all_mgq0)
    2161              : 
    2162           29 : 100 call timab(670,2,tsec)
    2163              : 
    2164           29 : end subroutine exc_build_ham
    2165              : !!***
    2166              : 
    2167              : !!****f* m_exc_build/wfd_all_mgq0
    2168              : !! NAME
    2169              : !!  wfd_all_mgq0
    2170              : !!
    2171              : !! FUNCTION
    2172              : !!
    2173              : !! INPUTS
    2174              : !!  Wfd<wfdgw_t>=Handler for the wavefunctions.
    2175              : !!  Cryst<crystal_t>=Info on the crystalline structure.
    2176              : !!  Qmesh<kmesh_t>=The list of q-points for epsilon^{-1} and related symmetry tables.
    2177              : !!  Gsph_x<gsphere_t>=G-sphere with the G-vectors in mgq0.
    2178              : !!  Vcp<vcoul_t>=The Coulomb interaction in reciprocal space. A cutoff can be used
    2179              : !!  Psps<Pseudopotential_type>=Variables related to pseudopotentials
    2180              : !!  Pawtab(Psps%ntypat)<pawtab_type>=PAW tabulated starting data.
    2181              : !!  Paw_pwff(Cryst%ntypat*Wfd%usepaw)<pawpwff_t>=Form factor used to calculate the onsite mat. elements of a plane wave.
    2182              : !!  lomo_spin(Wfd%nsppol)=Lowest occupied band for each spin
    2183              : !!  homo_spin(Wfd%nsppol)=Highest occupied band for each spin
    2184              : !!  humo_spin(Wfd%nsppol)=Highest unoccupied band for each spin
    2185              : !!  nfftot_osc=Total Number of FFT points used for the oscillator matrix elements.
    2186              : !!  ngfft_osc(18)=Info on the FFT algorithm used to calculate the oscillator matrix elements.
    2187              : !!  npweps=Number of G-vectors in mgq0.
    2188              : !!
    2189              : !! OUTPUT
    2190              : !!   mgq0(npweps,lomo_min:humo_max,lomo_min:humo_max,Wfd%nkibz,Wfd%nsppol)
    2191              : !!     Allocated here and filled with the matrix elements on each node.
    2192              : !!
    2193              : !! SOURCE
    2194              : 
    2195           23 : subroutine wfd_all_mgq0(Wfd,Cryst,Qmesh,Gsph_x,Vcp,&
    2196           23 : & Psps,Pawtab,Paw_pwff,lomo_spin,homo_spin,humo_spin,nfftot_osc,ngfft_osc,npweps,mgq0)
    2197              : 
    2198              : !Arguments ------------------------------------
    2199              : !scalars
    2200              :  integer,intent(in) :: nfftot_osc,npweps
    2201              :  type(kmesh_t),intent(in) :: Qmesh
    2202              :  type(crystal_t),intent(in) :: Cryst
    2203              :  type(vcoul_t),intent(in) :: Vcp
    2204              :  type(gsphere_t),intent(in) :: Gsph_x
    2205              :  type(Pseudopotential_type),intent(in) :: Psps
    2206              :  type(wfdgw_t),target,intent(inout) :: Wfd
    2207              : !arrays
    2208              :  integer,intent(in) :: lomo_spin(Wfd%nsppol),homo_spin(Wfd%nsppol),humo_spin(Wfd%nsppol)
    2209              :  integer,intent(in) :: ngfft_osc(18)
    2210              :  complex(gwp),allocatable,intent(out) :: mgq0(:,:,:,:,:)
    2211              :  type(Pawtab_type),intent(in) :: Pawtab(Psps%ntypat)
    2212              :  type(pawpwff_t),intent(in) :: Paw_pwff(Psps%ntypat*Wfd%usepaw)
    2213              : 
    2214              : !Local variables ------------------------------
    2215              : !scalars
    2216              :  integer,parameter :: map2sphere1=1,dim_rtwg1=1,ndat1=1
    2217              :  integer :: use_padfft,mgfft_osc,fftalga_osc,ii
    2218              :  integer :: ik_ibz,itim_k,isym_k,iq_bz,iq_ibz,isym_q,itim_q,iqbz0
    2219              :  integer :: ierr,iv,ic,spin,lomo_min,humo_max !,inv_ipw,ipw
    2220              :  real(dp) :: cpu,wall,gflops !q0vol,fcc_const
    2221              :  complex(dp) :: ph_mkt
    2222              :  character(len=500) :: msg
    2223              :  type(wave_t),pointer :: wave_v, wave_c
    2224              : !arrays
    2225           23 :  integer,allocatable :: igfftg0(:),task_distrib(:,:,:,:)
    2226           23 :  integer,allocatable :: gbound(:,:),id_tab(:)
    2227              :  real(dp) :: qbz(3),spinrot_k(4),tsec(2)
    2228           23 :  complex(gwp),allocatable :: rhotwg1(:)
    2229           23 :  complex(gwp),target,allocatable :: ur1(:),ur2(:)
    2230           23 :  complex(gwp),contiguous, pointer :: ptr_ur1(:),ptr_ur2(:)
    2231           23 :  type(pawcprj_type),allocatable :: Cp1(:,:),Cp2(:,:)
    2232           23 :  type(pawpwij_t),allocatable :: Pwij_q0(:)
    2233              : !************************************************************************
    2234              : 
    2235           23 :  call timab(671,1,tsec)
    2236              : 
    2237           23 :  ABI_CHECK(Wfd%nspinor==1,"nspinor==2 not coded")
    2238           92 :  ABI_CHECK(nfftot_osc==PRODUCT(ngfft_osc(1:3)),"mismatch in FFT size")
    2239              : 
    2240           71 :  lomo_min = MINVAL(lomo_spin); humo_max = MAXVAL(humo_spin)
    2241              : 
    2242           50 :  if ( ANY(ngfft_osc(1:3) /= Wfd%ngfft(1:3)) ) call wfd%change_ngfft(Cryst,Psps,ngfft_osc)
    2243              : 
    2244           92 :  mgfft_osc   = MAXVAL(ngfft_osc(1:3))
    2245           23 :  fftalga_osc = ngfft_osc(7)/100 !; fftalgc_osc=MOD(ngfft_osc(7),10)
    2246              : 
    2247              :  ! (temporary) Table used for the wavefunction in the IBZ.
    2248           69 :  ABI_MALLOC(id_tab, (Wfd%nfft))
    2249       482671 :  id_tab = (/(ii, ii=1,Wfd%nfft)/)
    2250              : 
    2251              :  ! Analytic integration of 4pi/q^2 over the volume element:
    2252              :  ! $4pi/V \int_V d^3q 1/q^2 =4pi bz_geometric_factor V^(-2/3)$
    2253              :  ! i_sz=4*pi*bz_geometry_factor*q0_vol**(-two_thirds) where q0_vol= V_BZ/N_k
    2254              :  ! bz_geometry_factor: sphere=7.79, fcc=7.44, sc=6.188, bcc=6.946, wz=5.255
    2255              :  ! (see gwa.pdf, appendix A.4)
    2256              : 
    2257              :  ! If q=0 and C=V then set up rho-twiddle(G=0) to reflect an
    2258              :  ! analytic integration of q**-2 over the volume element:
    2259              :  ! <q**-2> = 7.44 V**(-2/3)   (for fcc cell)
    2260              : 
    2261              :  ! q0vol = (8.0*pi**3) / (Cryst%ucvol*Kmesh%nbz)
    2262              :  ! fcc_const = SQRT(7.44*q0vol**(-2.0/3.0))
    2263              :  ! rtw = (6.0*pi**2/(Cryst%ucvol*Kmesh%nkbz))**(1./3.)
    2264              :  ! Average of (q+q')**-2 integration for head of Coulomb matrix
    2265              :  ! INTRTW(QL) = (2*pi*rtw + pi*(rtw**2/QL-QL)*LOG((QL+rtw)/(QL-rtw)))
    2266              :  ! &              * (Cryst%ucvol*Kmesh%nbz)/(2*pi)**3. * QL*QL
    2267              : 
    2268           23 :  if (Wfd%usepaw==1) then
    2269           14 :    ABI_MALLOC(Cp1,(Wfd%natom,Wfd%nspinor))
    2270            2 :    call pawcprj_alloc(Cp1,0,Wfd%nlmn_atm)
    2271           14 :    ABI_MALLOC(Cp2,(Wfd%natom,Wfd%nspinor))
    2272            2 :    call pawcprj_alloc(Cp2,0,Wfd%nlmn_atm)
    2273              :  end if
    2274              : 
    2275           69 :  ABI_MALLOC(ur1,(nfftot_osc*Wfd%nspinor))
    2276           46 :  ABI_MALLOC(ur2,(nfftot_osc*Wfd%nspinor))
    2277              : 
    2278              :  ! Identify q==0
    2279           23 :  iqbz0=0
    2280         1079 :  do iq_bz=1,Qmesh%nbz
    2281         1446 :    if (ALL(ABS(Qmesh%bz(:,iq_bz))<tol3)) iqbz0 = iq_bz
    2282              :  end do
    2283           23 :  ABI_CHECK(iqbz0/=0,"q=0 not found in q-point list!")
    2284              : 
    2285              :  ! * Get iq_ibz, and symmetries from iqbz0.
    2286           23 :  call qmesh%get_BZ_item(iqbz0,qbz,iq_ibz,isym_q,itim_q)
    2287              : 
    2288           23 :  if (Wfd%usepaw==1) then ! Prepare onsite contributions at q==0
    2289            9 :    ABI_MALLOC(Pwij_q0,(Cryst%ntypat))
    2290            2 :    call pawpwij_init(Pwij_q0,npweps,Qmesh%bz(:,iqbz0),Gsph_x%gvec,Cryst%rprimd,Psps,Pawtab,Paw_pwff)
    2291              :  end if
    2292              :  !
    2293              :  ! Tables for the FFT of the oscillators.
    2294              :  !  a) FFT index of the G sphere (only vertical transitions, unlike cchi0, no need to shift the sphere).
    2295              :  !  b) gbound table for the zero-padded FFT performed in rhotwg.
    2296           69 :  ABI_MALLOC(igfftg0,(Gsph_x%ng))
    2297           92 :  ABI_MALLOC(gbound,(2*mgfft_osc+8,2))
    2298           23 :  call Gsph_x%fft_tabs((/0,0,0/),mgfft_osc,ngfft_osc,use_padfft,gbound,igfftg0)
    2299           23 :  if ( ANY(fftalga_osc == (/2,4/)) ) use_padfft=0 ! Pad-FFT is not coded in rho_tw_g
    2300           23 :  if (use_padfft==0) then
    2301            0 :    ABI_FREE(gbound)
    2302            0 :    ABI_MALLOC(gbound,(2*mgfft_osc+8,2*use_padfft))
    2303              :  end if
    2304              : 
    2305           69 :  ABI_MALLOC(rhotwg1,(npweps))
    2306              : 
    2307          161 :  ABI_MALLOC_OR_DIE(mgq0, (npweps,lomo_min:humo_max,lomo_min:humo_max,Wfd%nkibz,Wfd%nsppol), ierr)
    2308      1317080 :  mgq0 = czero
    2309              : 
    2310           23 :  call cwtime(cpu,wall,gflops,"start")
    2311              : 
    2312           47 :  do spin=1,Wfd%nsppol
    2313              :    ! Distribute the calculation of the matrix elements.
    2314              :    ! processors have the entire set of wavefunctions hence we divide the workload
    2315              :    ! without checking if the pair of states is available. Last dimension is fake.
    2316          120 :    ABI_MALLOC(task_distrib,(lomo_spin(spin):humo_spin(spin),lomo_spin(spin):humo_spin(spin),Wfd%nkibz,1))
    2317           24 :    call xmpi_distab(Wfd%nproc,task_distrib)
    2318              : 
    2319              :    ! loop over the k-points in IBZ
    2320          887 :    do ik_ibz=1,Wfd%nkibz
    2321         8543 :      if ( ALL(task_distrib(:,:,ik_ibz,1)/= Wfd%my_rank) ) CYCLE
    2322              : 
    2323              :      ! Don't need to symmetrize the wavefunctions.
    2324         3035 :      itim_k=1; isym_k=1; ph_mkt=cone; spinrot_k=Cryst%spinrot(:,isym_k)
    2325              : 
    2326         4109 :      do iv=lomo_spin(spin),humo_spin(spin) ! Loop over band V
    2327         3478 :        if ( ALL(task_distrib(:,iv,ik_ibz,1)/=Wfd%my_rank) ) CYCLE
    2328              : 
    2329         3478 :        ABI_CHECK(wfd%get_wave_ptr(iv, ik_ibz, spin, wave_v, msg) == 0, msg)
    2330              : 
    2331         3478 :        if (wave_v%has_ur == WFD_STORED) then
    2332         2989 :          ptr_ur1 =>  wave_v%ur
    2333              :        else
    2334          489 :          call wfd%get_ur(iv,ik_ibz,spin,ur1)
    2335          489 :          ptr_ur1 =>  ur1
    2336              :        end if
    2337              : 
    2338         3478 :        if (Wfd%usepaw==1) call wfd%get_cprj(iv,ik_ibz,spin,Cryst,Cp1,sorted=.FALSE.)
    2339              : 
    2340              :        ! Loop over band C
    2341        24829 :        do ic=lomo_spin(spin),humo_spin(spin)
    2342        20488 :          if ( task_distrib(ic,iv,ik_ibz,1)/=Wfd%my_rank ) CYCLE
    2343              : 
    2344        20488 :          ABI_CHECK(wfd%get_wave_ptr(ic, ik_ibz, spin, wave_c, msg) == 0, msg)
    2345              : 
    2346        20488 :          if (wave_c%has_ur == WFD_STORED) then
    2347        17853 :            ptr_ur2 =>  wave_c%ur
    2348              :          else
    2349         2635 :            call wfd%get_ur(ic,ik_ibz,spin,ur2)
    2350         2635 :            ptr_ur2 =>  ur2
    2351              :          end if
    2352              : 
    2353        20488 :          if (Wfd%usepaw==1) call wfd%get_cprj(ic,ik_ibz,spin,Cryst,Cp2,sorted=.FALSE.)
    2354              : 
    2355              :          call rho_tw_g(Wfd%nspinor,npweps,nfftot_osc,ndat1,ngfft_osc,map2sphere1,use_padfft,igfftg0,gbound,&
    2356              :            ptr_ur1,1,id_tab,ph_mkt,spinrot_k,&
    2357              :            ptr_ur2,1,id_tab,ph_mkt,spinrot_k,&
    2358        20488 :            dim_rtwg1,rhotwg1)
    2359              : 
    2360        20488 :          if (Wfd%usepaw==1) then
    2361              :            ! Add PAW onsite contribution.
    2362          304 :            call paw_rho_tw_g(cryst,Pwij_q0,npweps,dim_rtwg1,Wfd%nspinor,Gsph_x%gvec,Cp1,Cp2,rhotwg1)
    2363              :          end if
    2364              : 
    2365              :          ! If q=0 treat Exchange and Coulomb-term independently
    2366        20488 :          if (iv <= homo_spin(spin) .and. ic <= homo_spin(spin) .or. &
    2367              :              iv >  homo_spin(spin) .and. ic >  homo_spin(spin)) then
    2368              : 
    2369        10424 :            if (iv/=ic) then !COULOMB term: C/=V: ignore them
    2370         6946 :              rhotwg1(1) = czero_gw
    2371              :            else
    2372              :              ! If q=0 and C=V then set up rho-twiddle(G=0) to reflect an
    2373              :              ! analytic integration of q**-2 over the volume element:
    2374              :              ! <q**-2> = 7.44 V**(-2/3)   (for fcc cell)
    2375              :              !rhotwg1(1) = fcc_const * qpg(1,iqbz0)
    2376         3478 :              rhotwg1(1) = SQRT(GWPC_CMPLX(Vcp%i_sz,zero)) / Vcp%vcqlwl_sqrt(1,1)
    2377              :              !if (vcut) rhotwg1(1) = 1.0
    2378              :            end if
    2379              : 
    2380              :          else
    2381              :            ! At present this term is set to zero
    2382              :            ! EXCHANGE term: limit value.
    2383              :            ! Set up rho-twiddle(G=0) using small vector q instead of zero and k.p perturbation theory (see notes)
    2384        10064 :            rhotwg1(1) = czero_gw
    2385              :          end if
    2386              : 
    2387       930890 :          mgq0(:,iv,ic,ik_ibz,spin) = rhotwg1(:)
    2388              :        end do !ic
    2389              :      end do !iv
    2390              :    end do !ik_ibz
    2391              : 
    2392           47 :    ABI_FREE(task_distrib)
    2393              :  end do !spin
    2394              : 
    2395              :  ! TODO: One can speedup the calculation by computing the upper triangle of the
    2396              :  ! matrix in (b,b') space and then take advantage of the symmetry property:
    2397              :  !
    2398              :  !   M_{k,0}{{bb'}(G)^* = M{k,0}{b'b'}(-G)
    2399              : 
    2400              : #if 0
    2401              :  !!!! $OMP PARALLEL DO COLLAPSE(3) PRIVATE(inv_ipw)
    2402              :  do spin=1,Wfd%nsppol
    2403              :    do ik_ibz=1,Wfd%nkibz
    2404              :      do iv=lomo_spin(spin),humo_spin(spin)
    2405              :        do ic=1,iv-1
    2406              :          do ipw=1,npweps
    2407              :            inv_ipw = gsph_x%g2mg(ipw)
    2408              :            mgq0(inv_ipw,ic,iv,ik_ibz,spin) = mgq0(ipw,iv,ic,ik_ibz,spin)
    2409              :          end do
    2410              :        end do
    2411              :      end do
    2412              :    end do
    2413              :  end do
    2414              : #endif
    2415              :  !
    2416              :  ! Gather matrix elements on each node.
    2417           23 :  call xmpi_sum(mgq0,Wfd%comm,ierr)
    2418              : 
    2419           23 :  call cwtime(cpu,wall,gflops,"stop")
    2420           23 :  write(msg,'(2(a,f9.6))')"cpu_time = ",cpu,", wall_time = ",wall
    2421           23 :  call wrtout(std_out, msg)
    2422              : 
    2423           23 :  ABI_FREE(rhotwg1)
    2424           23 :  ABI_FREE(igfftg0)
    2425           23 :  ABI_FREE(gbound)
    2426           23 :  ABI_FREE(ur1)
    2427           23 :  ABI_FREE(ur2)
    2428           23 :  ABI_FREE(id_tab)
    2429              : 
    2430           23 :  if (Wfd%usepaw==1) then
    2431              :    ! Deallocation for PAW.
    2432            2 :    call pawpwij_free(Pwij_q0)
    2433            5 :    ABI_FREE(Pwij_q0)
    2434            2 :    call pawcprj_free(Cp1)
    2435            6 :    ABI_FREE(Cp1)
    2436            2 :    call pawcprj_free(Cp2)
    2437            6 :    ABI_FREE(Cp2)
    2438              :  end if
    2439              : 
    2440           23 :  call timab(671,2,tsec)
    2441              : 
    2442           92 : end subroutine wfd_all_mgq0
    2443              : !!***
    2444              : 
    2445              : end module m_exc_build
    2446              : !!***
        

Generated by: LCOV version 2.3-1