LCOV - code coverage report
Current view: top level - src/71_bse - m_exc_itdiago.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 69.5 % 423 294
Test Date: 2026-09-19 15:24:51 Functions: 100.0 % 5 5

            Line data    Source code
       1              : !!****m* ABINIT/m_exc_itdiago
       2              : !! NAME
       3              : !! m_exc_itdiago
       4              : !!
       5              : !! FUNCTION
       6              : !!  Iterative diagonalization of the BSE Hamiltonian with band-by-band conjugate gradient method
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 2008-2026 ABINIT group (MG)
      10              : !!  This file is distributed under the terms of the
      11              : !!  GNU General Public License, see ~abinit/COPYING
      12              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13              : !!
      14              : !! SOURCE
      15              : 
      16              : #if defined HAVE_CONFIG_H
      17              : #include "config.h"
      18              : #endif
      19              : 
      20              : #include "abi_common.h"
      21              : 
      22              : MODULE m_exc_itdiago
      23              : 
      24              :  use defs_basis
      25              :  use m_bs_defs
      26              :  use m_errors
      27              :  use m_abicore
      28              :  use m_linalg_interfaces
      29              :  use m_hdr
      30              :  USE_MPI
      31              :  use m_xmpi
      32              : 
      33              :  use m_io_tools,      only : open_file
      34              :  use m_time,          only : cwtime
      35              :  use m_numeric_tools, only : stats_t, stats_eval
      36              :  use m_hide_lapack,   only : xhpev !xheev,
      37              :  use m_bse_io,        only : exc_read_rcblock
      38              : 
      39              :  implicit none
      40              : 
      41              :  private
      42              : 
      43              : #ifdef HAVE_MPI1
      44              :  include 'mpif.h'
      45              : #endif
      46              : 
      47              :  public :: exc_iterative_diago    ! Calculates eigenvalues and eigenvectors of the Resonant BSE Hamiltonian
      48              : !!***
      49              : 
      50              : CONTAINS  !===============================================================
      51              : !!***
      52              : 
      53              : !!****f* m_exc_itdiago/exc_iterative_diago
      54              : !!
      55              : !! NAME
      56              : !!  exc_iterative_diago
      57              : !!
      58              : !! FUNCTION
      59              : !!  Calculates eigenvalues and eigenvectors of the Hermitian excitonic Hamiltonian (coupling is neglected).
      60              : !!
      61              : !! INPUTS
      62              : !!  Bsp
      63              : !!    %nreh=Rank of the resonant block of the Hamiltonian.
      64              : !!    %nstates=Number of eigenstates required.
      65              : !!    %nline=Max number of line minimizations.
      66              : !!    %tolwfr=Tolerance on the residuals.
      67              : !!    %nbdbuf
      68              : !!    %nstep
      69              : !!  BS_files<excfiles>=Datatype storing names and files used in the Bethe-Salpeter code.
      70              : !!    %exh=Name of the file storing the excitonin resonant part.
      71              : !!    %out_eig_out=Name of the file where final results are store.
      72              : !!    %in_eig=Name of the file used to initialize the calculation.
      73              : !!  comm=MPI communicator.
      74              : !!
      75              : !! OUTPUT
      76              : !!  Eigenvalues and eigenvectors are written on file %out_eig
      77              : !!
      78              : !! NOTES
      79              : !!  Concernig the approach followed to parallelize this routine: the most important
      80              : !!  bottleneck is represent by the storage of the excitonic Hamiltonian since a
      81              : !!  large number of k-points is needed to obtain converged exciton energies.
      82              : !!  The number of eigenstates is usually much smaller than the rank of the full matrix,
      83              : !!  this is especially true if we are only interested in the binding energy of the
      84              : !!  exciton or in the excitonic states close to the single-particle gap.
      85              : !!  Therefore good scaling and good performance should be obtained by distributing
      86              : !!  the row of the excitonic Hamiltonian among the nodes while the required
      87              : !!  eigenvectors are duplicated on each node. The memory needed to stores the eigenvalues
      88              : !!  scales like nreh*nstates where nreh is the rank of the Hamiltonian and this might
      89              : !!  render the calculation unfeasible when nstates is large.
      90              : !!  On the other hand, having the complex set of trial eigenvectors on each node permits to parallelize
      91              : !!  tasks such as the application of the Hamiltonian as well as the orthogonalization or the sub-space rotation
      92              : !!  the later two algorithms represent the most CPU demanding part in standard KS calculations
      93              : !!  as they scale with the third power of the number of atoms.
      94              : !!  The conjugate direction and the gradient as well as Hphi are not distributed as the line minimization
      95              : !!  requires the evaluation of <cg_dir_|H_exc|cg_dir>.
      96              : !!  Note that this routine has been written having in mind an homogeneous network of machines.
      97              : !!  A network made of different CPU will lead to unpredictable results as each node has
      98              : !!  to check for the converge of the calculation.
      99              : !!
     100              : !! SOURCE
     101              : 
     102            1 : subroutine exc_iterative_diago(BSp,BS_files,Hdr_bse,prtvol,comm)
     103              : 
     104              : !Arguments ------------------------------------
     105              : !scalars
     106              :  integer,intent(in) :: comm,prtvol
     107              :  type(excparam),intent(in) :: BSp
     108              :  type(excfiles),intent(in) ::  BS_files
     109              :  type(Hdr_type),intent(in) :: Hdr_bse
     110              : 
     111              : !Local variables ------------------------------
     112              : !scalars
     113              :  integer,parameter :: STRICT=2,MEDIUM=1,WORST=0
     114              :  integer,parameter :: master=0
     115              :  integer(i8b) :: bsize_hmat,bsize_phi_block
     116              :  integer :: hexc_size,nstates,nline,nbdbuf,nstep
     117              :  integer :: cg_nsteps,my_t1,my_t2,my_nt
     118              :  integer :: ii,jj,state,line,max_nline
     119              :  integer :: cg_step,nbdbuf_,nsppol,ierr,nproc,my_rank
     120              :  real(dp) :: exc_gap,exc_maxene,norm,etrial,etrial_old,deltae,tolwfr
     121              : ! real(dp) :: deold
     122              :  real(dp) :: dhd,dhc,den,fac,poly,xx,root,swap,tan2th,diff,tolwfr_
     123              :  !complex(dp) :: cg_gamma,dotgg,old_dotgg
     124              :  real(dp) :: cg_gamma,dotgg,old_dotgg
     125              :  real(dp) :: max_resid,costh,sinth
     126              :  complex(dp) :: zz,kprc
     127              :  logical,parameter :: DEBUGME=.False.
     128              :  logical :: use_mpio,is_resonant,diago_is_real
     129              :  character(len=500) :: msg
     130              :  character(len=fnlen) :: hexc_fname,ihexc_fname,oeig_fname
     131              :  type(stats_t) :: stats
     132              : !arrays
     133            3 :  integer :: nline_for(Bsp%nstates),convergence_of(Bsp%nstates)
     134            3 :  real(dp) :: resid(Bsp%nstates),exc_energy(Bsp%nstates),rbuf2(2)
     135              : ! real(dp),allocatable :: gsc(:,:),cg(:,:)
     136              :  !complex,allocatable :: hexc(:,:)
     137            1 :  complex(dp),allocatable :: hexc(:,:),hji(:),vec_tmp(:)
     138            1 :  complex(dp),contiguous, pointer :: my_phi(:)
     139            1 :  real(dp),allocatable :: hexc_diagonal(:)
     140            1 :  complex(dp),target,allocatable :: phi_block(:,:)
     141            1 :  complex(dp),allocatable :: hphi(:) !,buffer_dpc(:)
     142            1 :  complex(dp),allocatable :: cg_dir(:),grad_dir(:),prc_dir(:)
     143            1 :  complex(dp),allocatable :: old_cg_dir(:)
     144              : !************************************************************************
     145              : 
     146              :  DBG_ENTER("COLL")
     147              : 
     148            1 :  if (Bsp%use_coupling>0) then
     149            0 :    ABI_ERROR("CG Method does not support coupling")
     150              :  end if
     151              : 
     152            1 :  nsppol = Hdr_bse%nsppol
     153            1 :  if (Hdr_bse%nsppol == 2) then
     154            0 :    ABI_WARNING("nsppol==2 with cg method is still under development")
     155              :  end if
     156              : 
     157            1 :  nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
     158              : 
     159            1 :  use_mpio=.FALSE.
     160              : #ifdef HAVE_MPI_IO
     161              :  use_mpio = (nproc > 1)
     162              : #endif
     163              :  use_mpio=.FALSE.
     164              :  !use_mpio = .TRUE.
     165              : 
     166            2 :  hexc_size = SUM(Bsp%nreh)
     167            1 :  nstates= Bsp%nstates
     168            1 :  nline  = Bsp%nline
     169            1 :  nbdbuf = Bsp%nbdbuf
     170            1 :  nstep  = Bsp%niter
     171            1 :  tolwfr = Bsp%cg_tolwfr
     172              : 
     173            1 :  write(msg,'(a,i0)')' Iterative diagonalization of the resonant excitonic Hamiltonian, Matrix size= ',hexc_size
     174            1 :  call wrtout(std_out,msg,"COLL")
     175            1 :  call wrtout(ab_out,msg,"COLL")
     176              : 
     177            1 :  ABI_CHECK(hexc_size>=nproc,"hexc_size<nproc!")
     178            1 :  ABI_CHECK(nstates <= hexc_size,"nstates cannot be greater that hexc size!")
     179              : 
     180              :  ! Divide the columns of the Hamiltonian among the nodes.
     181              :  call xmpi_split_work(hexc_size,comm,my_t1,my_t2)
     182              : 
     183            1 :  my_nt = my_t2-my_t1+1
     184            1 :  write(msg,'(a,i0,a)')" Will handle ",my_nt," columns of the excitonic Hamiltonian. "
     185            1 :  call wrtout(std_out,msg,"PERS")
     186              : 
     187            1 :  tolwfr_ = tolwfr
     188            1 :  if (tolwfr < 10**(-30)) then
     189            0 :    tolwfr_ = tol12
     190            0 :    write(msg,'(2(a,es12.4))')" Input tolwfr= ",tolwfr," Using tolwfr= ",tolwfr_
     191            0 :    ABI_WARNING(msg)
     192              :  end if
     193              : 
     194            1 :  cg_nsteps = nstep
     195            1 :  if (cg_nsteps<=0) then
     196            0 :    cg_nsteps = 30
     197            0 :    write(msg,'(2(a,es12.4))')" Input nstep= ",nstep," Using cg_nsteps= ",cg_nsteps
     198            0 :    ABI_WARNING(msg)
     199              :  end if
     200              : 
     201            1 :  nbdbuf_ = nbdbuf
     202            1 :  if (nbdbuf<=0) then
     203            0 :    nbdbuf_ = 4
     204            0 :    write(msg,'(2(a,i0))')" Input nbdbuf= ",nbdbuf," Using nbdbuf= ",nbdbuf_
     205            0 :    ABI_WARNING(msg)
     206              :  end if
     207              : 
     208              :  write(msg,"(4(a,i0,a),a,es12.4)")&
     209            1 : &  " cg_nsteps: ",cg_nsteps,ch10,&
     210            1 : &  " nstates:   ",nstates,ch10,&
     211            1 : &  " nline:     ",nline,ch10,&
     212            1 : &  " nbdbuf:    ",nbdbuf_,ch10,&
     213            2 : &  " tolwfr:    ",tolwfr_
     214            1 :  call wrtout(std_out,msg,"COLL")
     215            1 :  call wrtout(ab_out,msg,"COLL")
     216              : 
     217            1 :  bsize_hmat = 2*dp*hexc_size*my_nt
     218            1 :  write(msg,'(a,f8.1,a)')' Allocating excitonic Hamiltonian. Memory requested: ',bsize_hmat*b2Mb,' Mb.'
     219            1 :  call wrtout(std_out,msg,"COLL")
     220              : 
     221            3 :  ABI_MALLOC(hexc_diagonal,(my_t1:my_t2))
     222            4 :  ABI_MALLOC_OR_DIE(hexc,(hexc_size,my_t1:my_t2), ierr)
     223              :  !
     224              :  ! Read and construct full excitonic Hamiltonian using Hermiticity.
     225            1 :  if (BS_files%in_hreso /= BSE_NOFILE) then
     226            0 :    hexc_fname = BS_files%in_hreso
     227              :  else
     228            1 :    hexc_fname = BS_files%out_hreso
     229              :  end if
     230              :  !
     231              :  ! Read the resonant block from file.
     232            1 :  is_resonant=.TRUE.
     233            1 :  diago_is_real=(.not.BSp%have_complex_ene)
     234            1 :  call exc_read_rcblock(hexc_fname,Bsp,is_resonant,diago_is_real,nsppol,Bsp%nreh,hexc_size,my_t1,my_t2,hexc,use_mpio,comm)
     235              :  !
     236              :  ! Save diagonal part for preconditioning.
     237          385 :  do jj=my_t1,my_t2
     238          385 :    hexc_diagonal(jj) = REAL(hexc(jj,jj),kind=dp)
     239              :  end do
     240              :  !
     241              :  ! === Initialisation of the excitonic wavefunctions ===
     242              :  ! Two cases are possible.
     243              :  !   1) Fill trial eigenvectors with random numbers
     244              :  !      One needs to initialize wfs in such a way to avoid symmetry traps,
     245              :  !      and to avoid linear dependencies between wavefunctions
     246              :  !   2) Read eigenstates generated by a previous calculation.
     247              : 
     248            1 :  bsize_phi_block = 2*sp*my_nt*nstates
     249            1 :  write(msg,'(a,f8.1,a)')' Allocating BSE eigenvectors. Memory requested: ',bsize_phi_block*b2Mb,' Mb.'
     250            1 :  call wrtout(std_out,msg,"COLL",do_flush=.True.)
     251              : 
     252            4 :  ABI_MALLOC_OR_DIE(phi_block,(my_t1:my_t2,nstates), ierr)
     253              : 
     254            1 :  ihexc_fname = ""
     255            1 :  if (BS_files%in_eig /= BSE_NOFILE) ihexc_fname = BS_files%in_eig
     256              : 
     257            1 :  call exc_init_phi_block(ihexc_fname,use_mpio,comm)
     258              :  !
     259              :  ! =========================
     260              :  ! === Orthogonalization ===
     261              :  ! =========================
     262            1 :  call exc_cholesky_ortho()
     263              :  call exc_check_phi_block("First cholesky ortho")
     264              : 
     265              :  ! * Sub-space rotation.
     266            2 :  call exc_subspace_rotation()
     267              :  call exc_check_phi_block("First subspace_rotation")
     268              :  !
     269              :  ! ===========================
     270              :  ! ==== Conjugate gradient ===
     271              :  ! ===========================
     272            3 :  ABI_MALLOC(hphi,(hexc_size))
     273            2 :  ABI_MALLOC(cg_dir,(hexc_size))
     274            2 :  ABI_MALLOC(old_cg_dir,(hexc_size))
     275            2 :  ABI_MALLOC(grad_dir,(hexc_size))
     276            2 :  ABI_MALLOC(prc_dir,(hexc_size))
     277              : 
     278              :  max_nline=nline
     279           31 :  resid(:)=HUGE(one); nline_for(1:nstates)=max_nline; convergence_of(1:nstates)=WORST
     280              : 
     281           21 :  do cg_step=1,cg_nsteps
     282          220 :    do state=1,nstates
     283              : 
     284          200 :      if (prtvol>=10) then ! Tell us what is going on:
     285            0 :        write(msg,'(a,i6,2x,a,i3,a)')' --- exc_iterative_diago is called for state ',state,'for',nline_for(state),' lines'
     286            0 :        call wrtout(std_out,msg,'PERS')
     287              :      end if
     288              : 
     289              :      ! Extraction of the vector that is iteratively updated.
     290          200 :      my_phi => phi_block(my_t1:my_t2,state)
     291              : 
     292          933 :      do line=1,nline_for(state)
     293              :        ! Compute etrial=<phi|H|phi> and the residual [H-etrial]|phi>.
     294       283360 :        hphi = czero
     295              : #ifdef FC_NVHPC
     296              : !Buggy NVHPC compiler
     297              :        do jj=1,my_t2-my_t1+1;do ii=1,hexc_size
     298              :          hphi(ii)=hphi(ii)+hexc(ii,jj)*my_phi(jj)
     299              :        enddo ; enddo
     300              : #else
     301    326148832 :        hphi = MATMUL(hexc, my_phi)
     302              : #endif
     303          736 :        call xmpi_sum(hphi,comm,ierr)
     304              : 
     305       283360 :        etrial = DOT_PRODUCT(my_phi, hphi(my_t1:my_t2))
     306          736 :        call xmpi_sum(etrial,comm,ierr)
     307          736 :        exc_energy(state) =  etrial
     308              : 
     309              :        ! Compute residual (squared) norm.
     310       283360 :        grad_dir(my_t1:my_t2) = hphi(my_t1:my_t2) - etrial*my_phi
     311       283360 :        resid(state) =  DOT_PRODUCT(grad_dir(my_t1:my_t2), grad_dir(my_t1:my_t2))
     312          736 :        call xmpi_sum(resid(state),comm,ierr)
     313         1472 :        convergence_of(state) = convergence_degree(resid(state))
     314              :        !
     315              :        ! Check that etrial is decreasing on succeeding lines:
     316          736 :        if (line>1 .and. (etrial > etrial_old+tol12)) then
     317              :          write(msg,'(a,i8,a,1p,e14.6,a1,3x,a,1p,e14.6,a1)')&
     318            0 : &          'New trial exc_energy at line ',line,' = ',etrial,ch10,&
     319            0 : &          'is higher than former:',etrial_old,ch10
     320            0 :          ABI_WARNING(msg)
     321              :        end if
     322          736 :        etrial_old = etrial
     323              :        !
     324              :        ! If residual sufficiently small stop line minimization.
     325          736 :        if (convergence_of(state)==STRICT) then
     326           23 :          if (prtvol>=10) then
     327              :            write(msg,'(a,i4,a,i2,a,es12.4)')&
     328            0 : &            ' exc_iterative_diago: state ',state,' converged after ',line,&
     329            0 : &            ' line minimizations : resid =',resid(state)
     330            0 :            call wrtout(std_out,msg,'PERS')
     331              :          end if
     332              :          EXIT !line
     333              :        end if
     334              : 
     335              :        ! === PROJECT THE STEEPEST DESCENT DIRECTION OVER THE SUBSPACE ORTHOGONAL TO OTHER BANDS ===
     336              :        ! The following projection over the subspace orthogonal to occupied bands
     337              :        ! is optional. It is a bit more accurate, but doubles the number of N^3 ops.
     338              :        ! It is done only if ortalg>=0.
     339              : 
     340              :        ! Project the steepest descent direction: direc(2,npw)=<G|H|Cnk> - \sum_{(i<=n)} <G|H|Cik> , normalized.
     341              : 
     342              :        ! Grad_dir is already orthogonal to this band
     343         2139 :        ABI_MALLOC(hji,(nstates))
     344         7843 :        hji=czero
     345              : 
     346              :        ! MG TODO Don't know why here we sum over i=<=n!!!!!!!!
     347         7843 :        do jj=1,nstates
     348      2471971 :          if (jj/=state) hji(jj) = DOT_PRODUCT(phi_block(:,jj), hphi(my_t1:my_t2) )
     349              :        end do
     350          713 :        call xmpi_sum(hji,comm,ierr)
     351              : 
     352         7843 :        do jj=1,nstates
     353      2471971 :          if (jj/=state) grad_dir(my_t1:my_t2) = grad_dir(my_t1:my_t2) - hji(jj)*phi_block(:,jj)
     354              :        end do
     355          713 :        ABI_FREE(hji)
     356              :        !
     357              :        ! === PRECONDITION THE STEEPEST DESCENT DIRECTION ===
     358       274505 :        den = DOT_PRODUCT(grad_dir(my_t1:my_t2), hexc_diagonal(my_t1:my_t2)*grad_dir(my_t1:my_t2) )
     359          713 :        call xmpi_sum(den,comm,ierr)
     360              : 
     361       274505 :        do ii=my_t1,my_t2
     362              :          ! Teter polynomial ratio, modified according to Kresse, Furthmuller, PRB 54, 11169 (1996) [[cite:Kresse1996]]
     363       273792 :          xx = hexc_diagonal(ii)/den
     364       273792 :          poly=27._dp+xx*(18._dp+xx*(12._dp+xx*8._dp))
     365       273792 :          fac=poly/(poly+16._dp*xx**4)
     366       273792 :          kprc = fac*four/(three*den)
     367       274505 :          prc_dir(ii) = kprc * grad_dir(ii)
     368              :        end do
     369              :        !
     370              :        ! * PROJECT THE PRECOND. STEEPEST DESCENT DIRECTION OVER THE SUBSPACE ORTHOGONAL TO OTHER BANDS.
     371         2139 :        ABI_MALLOC(hji,(nstates))
     372         7843 :        hji=czero
     373         7843 :        do jj=1,nstates
     374      2745763 :          hji(jj) = DOT_PRODUCT(phi_block(:,jj), prc_dir(my_t1:my_t2) )
     375              :        end do
     376          713 :        call xmpi_sum(hji,comm,ierr)
     377              : 
     378         7843 :        do jj=1,nstates
     379      2745763 :          prc_dir(my_t1:my_t2) = prc_dir(my_t1:my_t2) - hji(jj)*phi_block(:,jj)
     380              :        end do
     381          713 :        ABI_FREE(hji)
     382              :        !
     383              :        ! === COMPUTE THE CONJUGATE-GRADIENT ===
     384       274505 :        dotgg = DOT_PRODUCT(prc_dir(my_t1:my_t2),grad_dir(my_t1:my_t2))
     385          713 :        call xmpi_sum(dotgg,comm,ierr)
     386              : 
     387          713 :        if (line==1) then ! At first iteration, cg_gamma is set to zero
     388          179 :          cg_gamma=zero
     389          179 :          old_dotgg=dotgg
     390        69094 :          cg_dir = prc_dir
     391        69094 :          old_cg_dir = cg_dir
     392              :        else
     393          534 :          cg_gamma=dotgg/old_dotgg
     394          534 :          old_dotgg=dotgg
     395              :          !write(std_out,*)"cg_gamma= ",cg_gamma
     396              :          !cg_dir = prc_dir + cg_gamma*cg_dir
     397       206124 :          cg_dir = prc_dir + cg_gamma*old_cg_dir !TODO check this, anyhow it is much faster.
     398       206124 :          old_cg_dir =cg_dir  ! old_cg_dir is used to store the previsou CG direction, cg_dir will be orthonormalized to the band
     399              :        end if
     400              :        !
     401              :        ! === PROJECTION OF THE CONJUGATED GRADIENT ===
     402       274505 :        zz = DOT_PRODUCT(my_phi, cg_dir(my_t1:my_t2))
     403          713 :        call xmpi_sum(zz,comm,ierr)
     404       274505 :        cg_dir(my_t1:my_t2) = cg_dir(my_t1:my_t2) -zz*my_phi(:)
     405              : 
     406       274505 :        norm = DOT_PRODUCT(cg_dir(my_t1:my_t2), cg_dir(my_t1:my_t2) )
     407          713 :        call xmpi_sum(norm,comm,ierr)
     408          713 :        norm = SQRT(norm)
     409       274505 :        cg_dir = cg_dir/norm ! Have to normalize it.
     410              : 
     411              :        ! Line minimization of the Raileigh functional.
     412         2139 :        ABI_MALLOC(vec_tmp,(hexc_size))
     413       274505 :        vec_tmp=czero
     414              : #ifdef FC_NVHPC
     415              : !Buggy NVHPC compiler
     416              :        do jj=my_t1,my_t2;do ii=1,hexc_size
     417              :          vec_tmp(ii)=vec_tmp(ii)+hexc(ii,jj-my_t1+1)*cg_dir(jj)
     418              :        enddo ; enddo
     419              : #else
     420    210820553 :        vec_tmp = MATMUL(hexc, cg_dir(my_t1:my_t2))
     421              : #endif
     422          713 :        call xmpi_sum(vec_tmp,comm,ierr)
     423              : 
     424              :        !if (my_rank==master) then
     425              :        !  write(777,*)"cg_step, state, line",cg_step, state, line
     426              :        !  write(777,*)vec_tmp
     427              :        !end if
     428              : 
     429       274505 :        dhd = DOT_PRODUCT( cg_dir(my_t1:my_t2), vec_tmp(my_t1:my_t2))  ! is this always real?
     430       274505 :        dhc = REAL( DOT_PRODUCT( my_phi, vec_tmp(my_t1:my_t2) ))
     431          713 :        ABI_FREE(vec_tmp)
     432              : 
     433         2139 :        rbuf2 = (/dhd,dhc/)
     434          713 :        call xmpi_sum(rbuf2,comm,ierr)
     435          713 :        dhd = rbuf2(1)
     436          713 :        dhc = rbuf2(2)
     437              : 
     438              :        !write(201*(my_rank+1),*)"cg_step, state, line dotgg dhd dhc",cg_step,state,line,dotgg,dhd,dhc
     439              : 
     440              : ! Taken from cgwf
     441              :        ! Compute tan(2 theta),sin(theta) and cos(theta)
     442          713 :        tan2th=2.0_dp*dhc/(etrial-dhd)
     443              : 
     444          713 :        if (abs(tan2th)<1.d-05) then
     445           67 :          costh=1.0_dp-0.125_dp*tan2th**2
     446           67 :          sinth=0.5_dp*tan2th*(1.0_dp-0.375_dp*tan2th**2)
     447              :          ! Check that result is above machine precision
     448              :          ! FIXME  This part is not safe on clusters made of different machines or different compiation options.
     449           67 :          if (abs(sinth)<epsilon(0._dp)) then
     450            0 :            write(msg, '(a,es16.4)' ) ' exc_iterative_diago: converged with tan2th= ',tan2th
     451            0 :            call wrtout(std_out,msg,'PERS')
     452            0 :            EXIT !Exit from the loop on line
     453              :          end if
     454              : 
     455              :        else
     456          646 :          root =sqrt(1.0_dp+tan2th**2)
     457          646 :          costh=sqrt(0.5_dp+0.5_dp/root)
     458          646 :          sinth=sign(sqrt(0.5_dp-0.5_dp/root),tan2th)
     459              :        end if
     460              :        !
     461              :        ! Check for lower of two possible roots (same sign as curvature at theta where slope is zero)
     462          713 :        diff=(etrial-dhd)
     463          713 :        if (diff>zero) then !   Swap c and d if value of diff is positive
     464           10 :          swap=costh
     465           10 :          costh=-sinth
     466           10 :          sinth=swap
     467           10 :          if (prtvol<0 .or. prtvol>=10) then
     468            0 :            write(msg,'(a,i4,es16.6)')' exc_iterative_diago: swap roots, line,diff= ',line,diff
     469            0 :            call wrtout(std_out,msg,'PERS')
     470              :          end if
     471              :        end if
     472              :        !
     473              :        ! === GENERATE NEW |wf>, H|wf>  =============
     474       274505 :        my_phi = costh*my_phi + sinth*cg_dir(my_t1:my_t2)
     475              :        !write(100*(my_rank+1),*)"cg_step state, line costh sinth etrial",cg_step,state,line,costh,sinth,etrial
     476              : !end  taken from cgwf
     477              : 
     478              :        !norm = SQRT( DOT_PRODUCT(my_phi,my_phi) )
     479              :        !my_phi = my_phi /norm
     480              :        !write(std_out,*)norm
     481              :        !write(std_out,*)DOT_PRODUCT(hphi,my_phi),cos(theta_min)
     482              : 
     483              :        ! ======================================================================
     484              :        ! =========== CHECK CONVERGENCE AGAINST TRIAL ENERGY ===================
     485              :        ! ======================================================================
     486              :        ! Compute delta(E)
     487              :        !deltae=chc*(costh**2-1._dp)+dhd*sinth**2+2._dp*costh*sinth*dhc
     488         8089 :        deltae=etrial*(costh**2-1._dp)+dhd*sinth**2+2._dp*costh*sinth*dhc
     489              : 
     490              :        ! Check convergence and eventually exit
     491              :        ! if (line==1) then
     492              :        !   deold=deltae
     493              :        ! else if (abs(deltae)<0.005_dp*abs(deold) .and. line/=nline_for(state))then
     494              :        !  if (prtvol>=10)then
     495              :        !   write(msg, '(a,i4,1x,a,1p,e12.4,a,e12.4,a)' ) &
     496              :        !&   ' cgwf: line',line,&
     497              :        !&   ' deltae=',deltae,' < 0.005*',deold,' =>skip lines'
     498              :        !   call wrtout(std_out,msg,'PERS')
     499              :        !  end if
     500              :        !  exc_energy(state) = exc_energy(state) + deltae
     501              :        !  EXIT
     502              :        ! end if
     503              :      end do ! LOOP FOR A GIVEN BAND. Note that there are three "exit" instructions inside
     504              :      ! Modify nline_for(state) according to converge degree.
     505              :      !if (convergence_of(state) == STRICT) nline_for(state) = MAX(max_nline-2,2)
     506              :      !if (convergence_of(state) == MEDIUM) nline_for(state) = MAX(max_nline-1,2)
     507              :      !if (convergence_of(state) == WORST ) nline_for(state) = max_nline
     508              :    end do !state
     509              : 
     510           20 :    if (prtvol>2) then
     511            0 :      do ii=0,(nstates-1)/8
     512            0 :        write(msg,'(a,8es10.2)')' res:',(resid(state),state=1+ii*8,MIN(nstates,8+ii*8))
     513            0 :        call wrtout(std_out,msg,'COLL')
     514              :      end do
     515            0 :      do ii=0,(nstates-1)/8
     516            0 :        write(msg,'(a,8es10.2)')' ene:',(exc_energy(state),state=1+ii*8,MIN(nstates,8+ii*8))
     517            0 :        call wrtout(std_out,msg,'COLL')
     518              :      end do
     519              :    end if
     520              : 
     521           20 :    write(msg,'(a,i0)')"After cg_step: ",cg_step
     522              :    call exc_check_phi_block(msg)
     523              : 
     524              :    ! Find largest residual over bands and Print residuals
     525          160 :    max_resid=MAXVAL( resid(:MAX(1,nstates-nbdbuf_)) )
     526              : 
     527           20 :    if (max_resid < tolwfr_) then
     528              :      write(msg,'(a,i0,2(a,es10.2),a,i0,a)')&
     529            0 : &      " After ",cg_step," iterations, max_resid= ",max_resid," < tolwfr= ",tolwfr_," ( Excluding nbdbuf= ",nbdbuf_,")"
     530            0 :      call wrtout(std_out,msg,'COLL')
     531            0 :      EXIT ! cg_step
     532              :    end if
     533              : 
     534              :    if (cg_step==1.or.MOD(cg_step,1)==0) then
     535           20 :      call wrtout(std_out," Subspace rotation + exc_cholesky_ortho ","COLL")
     536              : 
     537           20 :      call exc_subspace_rotation()
     538           20 :      call exc_cholesky_ortho()
     539              : 
     540              :      !mcg=hexc_size; mgsc=hexc_size; useoverlap=0
     541              :      !allocate(cg(2,mcg),gsc(2,mgsc*useoverlap))
     542              :      !do ii=1,nstates
     543              :      ! cg(1,:) = REAL (phi_block(:,ii))
     544              :      ! cg(2,:) = AIMAG(phi_block(:,ii))
     545              :      ! call fxphas(cg,gsc,0,0,1,mcg,mgsc,MPI_enreg_seq,1,hexc_size,useoverlap)
     546              :      ! phi_block(:,ii)=CMPLX(cg(1,:),cg(2,:))
     547              :      !end do
     548              :      !deallocate(cg,gsc)
     549              : 
     550              :    end if
     551              : 
     552              : !XG20141126 : At present, keep this fake test. Seems that there is some bug on shiva
     553              : !(compiler ?) so that the result is erroneous without it. Even suppressing the
     554              : !"stop" instruction triggers the bug ...
     555            1 :      if(cg_step==cg_nsteps+1)then
     556              :        write(std_out,*)' One should not be here : cg_step==cg_nsteps+1 '
     557              :        stop
     558              :      endif
     559              : 
     560              :  end do !cg_step
     561              : 
     562              :  ! Release some memory before entering RMM-DIIS
     563            1 :  ABI_FREE(hphi)
     564            1 :  ABI_FREE(cg_dir)
     565            1 :  ABI_FREE(old_cg_dir)
     566            1 :  ABI_FREE(grad_dir)
     567            1 :  ABI_FREE(prc_dir)
     568              : 
     569            3 :  do ii=0,(nstates-1)/8
     570            2 :    write(msg,'(a,8es10.2)')' res:',(resid(state),state=1+ii*8,min(nstates,8+ii*8))
     571            3 :    call wrtout(std_out,msg,'COLL')
     572              :  end do
     573            3 :  do ii=0,(nstates-1)/8
     574            2 :    write(msg,'(a,8es10.2)')' ene:',(exc_energy(state),state=1+ii*8,min(nstates,8+ii*8))
     575            3 :    call wrtout(std_out,msg,'COLL')
     576              :  end do
     577              : 
     578            1 :  stats = stats_eval(resid)
     579              : 
     580              :  write(msg,"(4(a,es10.2))")&
     581            1 : &  ". Residuals: min value: ",stats%min,", Max value: ",stats%max,", mean: ",stats%mean,", stdev: ",stats%stdev
     582            1 :  call wrtout(std_out,msg)
     583            1 :  call wrtout(ab_out,msg)
     584              : 
     585            1 :  if (max_resid > tolwfr_) then
     586            1 :    write(msg,'(2a,i5,2a,2(a,es10.2),a,i3,a)')ch10,&
     587            1 : &    " WARNING: conjugate-gradient not converged after ",cg_step," iterations.",ch10,&
     588            2 : &    " max_resid= ",max_resid," > tolwfr= ",tolwfr_," ( Excluding nbdbuf= ",nbdbuf_,")"
     589            1 :    call wrtout(ab_out,msg,'COLL')
     590            1 :    call wrtout(std_out,msg,'COLL')
     591              :  end if
     592              : 
     593           12 :  exc_gap    = MINVAL(exc_energy)
     594           12 :  exc_maxene = MAXVAL(exc_energy)
     595              : 
     596            1 :  write(msg,'(a,2(a,f7.2,2a))')ch10,&
     597            1 : &  " First excitonic eigenvalue= ",exc_gap*Ha_eV,   " [eV]. ",ch10,&
     598            2 : &  " Last  excitonic eigenvalue= ",exc_maxene*Ha_eV," [eV]. ",ch10
     599            1 :  call wrtout(std_out,msg,"COLL")
     600            1 :  call wrtout(ab_out,msg,"COLL")
     601              : 
     602              :  call exc_check_phi_block("END OF CONJUGATE-GRADIENT")
     603              : 
     604            0 :  ABI_FREE(hexc)
     605            1 :  ABI_FREE(hexc_diagonal)
     606              :  !
     607              :  ! =====================================
     608              :  ! ==== Write final results on file ====
     609              :  ! =====================================
     610            1 :  oeig_fname = BS_files%out_eig
     611            1 :  if (oeig_fname== BSE_NOFILE) then
     612            0 :    ABI_WARNING("oeig_fname was set to "//TRIM(BSE_NOFILE))
     613            0 :    oeig_fname = TRIM(BS_files%out_basename)//"_BSEIG"
     614            0 :    ABI_WARNING("using oeig_fname : "//TRIM(oeig_fname))
     615              :  end if
     616              : 
     617            1 :  call exc_write_phi_block(oeig_fname,use_mpio)
     618              : 
     619            1 :  ABI_FREE(phi_block)
     620              : 
     621            3 :  call xmpi_barrier(comm)
     622              : 
     623              :  DBG_EXIT("COLL")
     624              : 
     625              : CONTAINS  !===========================================================
     626              : !!***
     627              : 
     628              : !----------------------------------------------------------------------
     629              : 
     630              : !!****f* m_exc_itdiago/exc_init_phi_block
     631              : !! NAME
     632              : !! exc_init_phi_block
     633              : !!
     634              : !! FUNCTION
     635              : !!  Initialize the eigenstates either from file or fill them with random number
     636              : !!  if restart file is not available
     637              : !!
     638              : !! INPUTS
     639              : !!  ihexc_fname=
     640              : !!    Name of the file from which the eigenvectors will be read.
     641              : !!    Empty string to initialize trial eigenvectors with random numbers.
     642              : !!
     643              : !! SIDE EFFECTS
     644              : !!   phi_block(my_t1:my_t2,nstates)=Contains the trial eigenstates.
     645              : !!
     646              : !! SOURCE
     647              : 
     648            1 : subroutine exc_init_phi_block(ihexc_fname,use_mpio,comm)
     649              : 
     650              : !Arguments ------------------------------------
     651              : !scalars
     652              :  integer,intent(in) :: comm
     653              :  logical,intent(in) :: use_mpio
     654              :  character(len=*),intent(in) :: ihexc_fname
     655              : 
     656              : !Local variables ------------------------------
     657              :  integer :: eig_unt,hexc_size_restart,ii,state,seed
     658              :  integer ::  fold1,fold2,foldim,foldre
     659              :  real(dp) :: cputime,walltime,gflops
     660              :  character(len=500) :: errmsg
     661              : !arrays
     662            1 :  complex(dp),allocatable :: buffer_dpc(:)
     663              : #ifdef HAVE_MPI_IO
     664              :  integer:: amode,mpi_fh,mpi_err,old_type,etype,eig_type,my_nel,ierr,my_nrows
     665              :  integer(XMPI_OFFSET_KIND) :: ehdr_offset,my_offset,my_offpad,fmarker
     666            1 :  integer(XMPI_OFFSET_KIND),allocatable :: bsize_frecord(:)
     667              :  integer :: array_of_sizes(2),array_of_subsizes(2),array_of_starts(2)
     668              : #endif
     669              : !************************************************************************
     670              : 
     671            1 :  if (LEN_TRIM(ihexc_fname) == 0) then
     672            1 :    call wrtout(std_out," Initializing eigenvectors with random numbers","COLL")
     673              :    !
     674              :    ! Use random number generator. For portability, use only integer numbers
     675              :    ! The series of couples (fold1,fold2) is periodic with a period of
     676              :    ! 3x5x7x11x13x17x19x23x29x31, that is, larger than 2**32, the largest integer*4
     677              :    ! fold1 is between 0 and 34, fold2 is between 0 and 114. As sums of five
     678              :    ! uniform random variables, their distribution is close to a gaussian
     679              :    ! the gaussian distributions are folded, in order to be back to a uniform distribution
     680              :    ! foldre is between 0 and 20, foldim is between 0 and 18.
     681              :    !
     682           11 :    do state=1,nstates
     683         3851 :      do ii=my_t1,my_t2
     684         3840 :        seed=ii+(state-1)*hexc_size ! Different seed for different transitions and bands
     685         3840 :        fold1 =mod(seed,3)+mod(seed,5)+mod(seed,7)+mod(seed,11)+mod(seed,13)
     686         3840 :        fold2 =mod(seed,17)+mod(seed,19)+mod(seed,23)+mod(seed,29)+mod(seed,31)
     687         3840 :        foldre=mod(fold1+fold2,21)
     688         3840 :        foldim=mod(3*fold1+2*fold2,19)
     689              : 
     690         3850 :        phi_block(ii,state) = DCMPLX(foldre,foldim)
     691              :      end do
     692              :    end do
     693              : 
     694              :  else
     695              : 
     696            0 :    call cwtime(cputime, walltime, gflops, "start")
     697              : 
     698            0 :    if (.not.use_mpio) then
     699            0 :      call wrtout(std_out," Initializing eigenvectors from file: "//TRIM(ihexc_fname)//" using Fortran IO.","COLL")
     700              : 
     701            0 :      if (open_file(ihexc_fname,msg,newunit=eig_unt,form='unformatted',status="old") /=0 ) then
     702            0 :        ABI_ERROR(msg)
     703              :      end if
     704              : 
     705            0 :      read(eig_unt, err=10, iomsg=errmsg) hexc_size_restart
     706            0 :      ABI_CHECK(hexc_size_restart==hexc_size,"hexc_size_restart /= hexc_size")
     707            0 :      read(eig_unt, err=10, iomsg=errmsg) !skip DCMPLX(exevl(1:hexc_size))
     708              : 
     709            0 :      ABI_MALLOC(buffer_dpc,(hexc_size))
     710            0 :      do ii=1,nstates
     711            0 :        read(eig_unt, err=10, iomsg=errmsg) buffer_dpc
     712            0 :        phi_block(my_t1:my_t2,ii) = buffer_dpc(my_t1:my_t2)
     713              :      end do
     714            0 :      ABI_FREE(buffer_dpc)
     715              : 
     716            0 :      close(eig_unt, err=10, iomsg=errmsg)
     717              :    else
     718            0 :      call wrtout(std_out," Initializing eigenvectors from file: "//TRIM(ihexc_fname)//" using MPI-IO.","COLL")
     719              : #ifdef HAVE_MPI_IO
     720              :      !
     721              :      ! Open the file with MPI-IO
     722            0 :      amode=MPI_MODE_RDONLY
     723              : 
     724            0 :      call MPI_FILE_OPEN(comm, ihexc_fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
     725            0 :      msg = " MPI_IO error opening file: "//TRIM(ihexc_fname)
     726            0 :      ABI_CHECK_MPI(mpi_err,msg)
     727              : 
     728              :      ! Move the file pointer to skip the first two records.
     729            0 :      ehdr_offset=0
     730            0 :      call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,mpi_err)
     731            0 :      write(std_out,*)"fmarker first record ",fmarker
     732            0 :      call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,mpi_err)
     733            0 :      write(std_out,*)"fmarker first record ",fmarker
     734              :      !%call hdr_mpio_skip(mpi_fh,fform,ehdr_offset)
     735              :      !%ehdr_offset = 4*xmpio_bsize_frm + xmpio_bsize_int + nstates*xmpio_bsize_dpc
     736              : 
     737            0 :      etype=MPI_BYTE; old_type=MPI_DOUBLE_COMPLEX
     738              : 
     739            0 :      my_nrows=my_t2-my_t1+1; old_type=MPI_DOUBLE_COMPLEX
     740            0 :      array_of_sizes    = (/hexc_size,nstates/)
     741            0 :      array_of_subsizes = (/my_nrows,nstates/)
     742            0 :      array_of_starts   = (/my_t1,1/)
     743            0 :      call xmpio_create_fsubarray_2D(array_of_sizes,array_of_subsizes,array_of_starts,old_type,eig_type,my_offpad,mpi_err)
     744            0 :      ABI_CHECK_MPI(mpi_err,"fsubarray_2D")
     745              :      !
     746              :      ! Each node uses a different offset to skip the header and the blocks written by the other CPUs.
     747            0 :      my_offset = ehdr_offset + my_offpad
     748              : 
     749            0 :      call MPI_FILE_SET_VIEW(mpi_fh, my_offset, etype, eig_type, 'native', MPI_INFO_NULL, mpi_err)
     750            0 :      ABI_CHECK_MPI(mpi_err,"SET_VIEW")
     751              : 
     752            0 :      call MPI_TYPE_FREE(eig_type,mpi_err)
     753            0 :      ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
     754              : 
     755            0 :      my_nel = my_nrows*nstates
     756            0 :      call MPI_FILE_READ_ALL(mpi_fh, phi_block, my_nel, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
     757            0 :      ABI_CHECK_MPI(mpi_err,"FILE_READ")
     758              : 
     759              :      ! It seems that personal calls make the code stuck
     760              :      ! check the fortran markers.
     761            0 :      ABI_MALLOC(bsize_frecord,(nstates))
     762            0 :      bsize_frecord = hexc_size * xmpi_bsize_dpc
     763              :      ! ehdr_offset points to the end of the header.
     764            0 :      call xmpio_check_frmarkers(mpi_fh,ehdr_offset,xmpio_collective,nstates,bsize_frecord,ierr)
     765            0 :      ABI_CHECK(ierr==0,"Error in Fortran markers")
     766            0 :      ABI_FREE(bsize_frecord)
     767              :      !
     768              :      ! Close the file.
     769            0 :      call MPI_FILE_CLOSE(mpi_fh, mpi_err)
     770            0 :      ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
     771              : #else
     772              :      ABI_ERROR("You should not be here")
     773              : #endif
     774              :    end if
     775              : 
     776            0 :    call cwtime(cputime, walltime, gflops, "stop")
     777            0 :    write(msg,'(2(a,f9.1),a)')" IO operation completed. cpu_time: ",cputime,"[s], walltime: ",walltime," [s]"
     778            0 :    call wrtout(std_out, msg, "COLL", do_flush=.True.)
     779              :  end if
     780              : 
     781            1 :  return
     782              : 
     783              :  ! Handle IO-error
     784              : 10 continue
     785            0 :  ABI_ERROR(errmsg)
     786              : 
     787            1 : end subroutine exc_init_phi_block
     788              : !!***
     789              : 
     790              : !----------------------------------------------------------------------
     791              : 
     792              : !!****f* m_exc_itdiago/exc_write_phi_block
     793              : !! NAME
     794              : !! exc_write_phi_block
     795              : !!
     796              : !! FUNCTION
     797              : !!  Write phi_block on the Fortran file oeig_fname.
     798              : !!
     799              : !! SOURCE
     800              : 
     801            1 : subroutine exc_write_phi_block(oeig_fname,use_mpio)
     802              : 
     803              : !Arguments ------------------------------------
     804              : !scalars
     805              :  character(len=*),intent(in) :: oeig_fname
     806              :  logical,intent(in) :: use_mpio
     807              : 
     808              : !Local variables ------------------------------
     809              :  integer :: eig_unt,state,mpi_err !,fform
     810              :  real(dp) :: cputime,walltime,gflops
     811              :  character(len=500) :: msg,errmsg
     812              : ! type(Hdr_type) :: hexc_Hdr
     813              :  logical :: do_ep_lifetime
     814              : !!arrays
     815            1 :  complex(dp),allocatable :: buffer_dpc(:)
     816              : #ifdef HAVE_MPI_IO
     817              :  integer:: amode,mpi_fh,old_type,etype,eig_type,my_nel,ierr,my_nrows
     818              :  integer(XMPI_OFFSET_KIND) :: ehdr_offset,my_offset,my_offpad,fmarker
     819            1 :  integer(XMPI_OFFSET_KIND),allocatable :: bsize_frecord(:)
     820              :  integer :: array_of_sizes(2),array_of_subsizes(2),array_of_starts(2)
     821              : #endif
     822              : !************************************************************************
     823              : 
     824            1 :  do_ep_lifetime = .FALSE.
     825              : 
     826            1 :  call cwtime(cputime, walltime, gflops, "start")
     827              : 
     828            1 :  if (.not.use_mpio) then
     829              : 
     830              :    ! * Master writes the header.
     831            1 :    if (my_rank==master) then
     832            1 :      call wrtout(std_out," Writing eigenstates on file "//TRIM(oeig_fname)//" via Fortran-IO","COLL")
     833            1 :      if (open_file(oeig_fname,msg, newunit=eig_unt, form='unformatted') /= 0) then
     834            0 :        ABI_ERROR(msg)
     835              :      end if
     836            1 :      write(eig_unt, err=10, iomsg=errmsg) do_ep_lifetime
     837            1 :      write(eig_unt, err=10, iomsg=errmsg) hexc_size, nstates
     838           11 :      write(eig_unt, err=10, iomsg=errmsg) CMPLX(exc_energy(1:nstates),kind=dp)
     839              :    end if
     840              : 
     841              :    ! Wavefunctions are gathered on the master node band-by-band.
     842              :    ! TODO bands should be treated in blocks to minimize the number of MPI calls.
     843            3 :    ABI_MALLOC_OR_DIE(buffer_dpc,(hexc_size), ierr)
     844              : 
     845           11 :    do state=1,nstates
     846         3850 :      buffer_dpc=czero
     847         3850 :      buffer_dpc(my_t1:my_t2) = phi_block(:,state)
     848           10 :      call xmpi_sum_master(buffer_dpc,master,comm,mpi_err)
     849           11 :      if (my_rank==master) write(eig_unt, err=10, iomsg=errmsg) buffer_dpc(1:hexc_size)
     850              :    end do
     851            1 :    ABI_FREE(buffer_dpc)
     852              : 
     853            1 :    if (my_rank==master) close(eig_unt, err=10, iomsg=errmsg)
     854              : 
     855              :  else
     856              : #ifdef HAVE_MPI_IO
     857            0 :    call wrtout(std_out," Writing eigenstates on file "//TRIM(oeig_fname)//" with MPI-IO","COLL")
     858              : 
     859              :    ! Write the header.
     860            0 :    if (my_rank==master) then
     861              :      ! Write header using Fortran primitives.
     862            0 :      if (open_file(oeig_fname,msg,newunit=eig_unt,form='unformatted') /= 0) then
     863            0 :        ABI_ERROR(msg)
     864              :      end if
     865            0 :      write(eig_unt, err=10, iomsg=errmsg) nstates
     866            0 :      write(eig_unt, err=10, iomsg=errmsg) CMPLX(exc_energy(1:nstates),kind=dp)
     867              :      ! TODO: change setup_bse so that Hdr_bse reflects the parameters of the run.
     868            0 :      close(eig_unt, err=10, iomsg=errmsg)
     869              :    end if
     870              : 
     871            0 :    call xmpi_barrier(comm)
     872              : 
     873              :    ! Open the file with MPI-IO
     874            0 :    amode=MPI_MODE_RDWR
     875              : 
     876            0 :    call MPI_FILE_OPEN(comm, oeig_fname, amode, MPI_INFO_NULL, mpi_fh, mpi_err)
     877            0 :    msg = " MPI_IO error opening file: "//TRIM(oeig_fname)
     878            0 :    ABI_CHECK_MPI(mpi_err,msg)
     879              : 
     880              :    ! Move the file pointer to skip the first two records.
     881            0 :    ehdr_offset=0
     882            0 :    call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,mpi_err)
     883              :    !write(std_out,*)"fmarker first record ",fmarker
     884            0 :    call xmpio_read_frm(mpi_fh,ehdr_offset,xmpio_collective,fmarker,mpi_err)
     885              :    !write(std_out,*)"fmarker first record ",fmarker
     886              :    !$call hdr_mpio_skip(mpi_fh,fform,ehdr_offset)
     887              :    !$ehdr_offset = 4*xmpio_bsize_frm + xmpio_bsize_int + nstates*xmpio_bsize_dpc
     888              : 
     889            0 :    etype=MPI_BYTE; old_type=MPI_DOUBLE_COMPLEX
     890              : 
     891            0 :    my_nrows=my_t2-my_t1+1; old_type=MPI_DOUBLE_COMPLEX
     892            0 :    array_of_sizes    = (/hexc_size,nstates/)
     893            0 :    array_of_subsizes = (/my_nrows,nstates/)
     894            0 :    array_of_starts   = (/my_t1,1/)
     895            0 :    call xmpio_create_fsubarray_2D(array_of_sizes,array_of_subsizes,array_of_starts,old_type,eig_type,my_offpad,mpi_err)
     896            0 :    ABI_CHECK_MPI(mpi_err,"fsubarray_2D")
     897              :    !
     898              :    ! Each node uses a different offset to skip the header and the blocks written by the other CPUs.
     899            0 :    my_offset = ehdr_offset + my_offpad
     900              : 
     901            0 :    call MPI_FILE_SET_VIEW(mpi_fh, my_offset, etype, eig_type, 'native', MPI_INFO_NULL, mpi_err)
     902            0 :    ABI_CHECK_MPI(mpi_err,"SET_VIEW")
     903              : 
     904            0 :    call MPI_TYPE_FREE(eig_type,mpi_err)
     905            0 :    ABI_CHECK_MPI(mpi_err,"MPI_TYPE_FREE")
     906              : 
     907            0 :    my_nel = my_nrows*nstates
     908            0 :    call MPI_FILE_WRITE_ALL(mpi_fh, phi_block, my_nel, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpi_err)
     909            0 :    ABI_CHECK_MPI(mpi_err,"FILE_WRITE")
     910              : 
     911              :    ! It seems that personal calls make the code stuck
     912            0 :    ABI_MALLOC(bsize_frecord,(nstates))
     913            0 :    bsize_frecord = hexc_size * xmpi_bsize_dpc
     914              :    ! ehdr_offset points to the end of the header.
     915            0 :    call xmpio_write_frmarkers(mpi_fh,ehdr_offset,xmpio_collective,nstates,bsize_frecord,ierr)
     916            0 :    ABI_CHECK(ierr==0,"Error while writing Fortran markers")
     917            0 :    ABI_FREE(bsize_frecord)
     918              :    !
     919              :    ! Close the file.
     920            0 :    call MPI_FILE_CLOSE(mpi_fh, mpi_err)
     921            0 :    ABI_CHECK_MPI(mpi_err,"FILE_CLOSE")
     922              : #else
     923              :    ABI_ERROR("MPI-IO support not enabled")
     924              : #endif
     925              :  end if
     926              : 
     927            1 :  call cwtime(cputime, walltime, gflops, "stop")
     928            1 :  write(msg,'(2(a,f9.1),a)')" IO operation completed. cpu_time: ",cputime,"[s], walltime: ",walltime," [s]"
     929            1 :  call wrtout(std_out, msg, "COLL", do_flush=.True.)
     930              : 
     931            1 :  return
     932              : 
     933              :  ! Handle IO-error
     934              : 10 continue
     935            0 :  ABI_ERROR(errmsg)
     936              : 
     937            1 : end subroutine exc_write_phi_block
     938              : !!***
     939              : 
     940              : !----------------------------------------------------------------------
     941              : 
     942              : !!****f* m_exc_itdiago/exc_subspace_rotation
     943              : !! NAME
     944              : !! exc_subspace_rotation
     945              : !!
     946              : !! FUNCTION
     947              : !!  This routine performs the subspace rotation.
     948              : !!
     949              : !! SIDE EFFECTS
     950              : !!   phi_block(my_t1:my_t2,nstates)=Contains the trial eigenstates.
     951              : !!
     952              : !! SOURCE
     953              : 
     954           21 : subroutine exc_subspace_rotation()
     955              : 
     956              : !Local variables ------------------------------
     957              :  integer :: ii,jj,ipack,ierr
     958              : !arrays
     959           21 :  real(dp),allocatable :: sub_ene(:)
     960              : ! real(dp),allocatable :: evec(:,:)
     961           21 :  complex(dp),allocatable :: sub_ham(:,:),sub_pham(:),hphi_tot(:)
     962              : ! complex(dp),allocatable :: phi_tmp(:,:)
     963              : !************************************************************************
     964              : 
     965              :  ! * Sub-space rotation. Calculate <phi_i|H|phi_j> in packed form.
     966              :  ! TODO: this part can be rewritten using BLAS3 routines.
     967              : 
     968           63 :  ABI_MALLOC(hphi_tot,(hexc_size))
     969           63 :  ABI_MALLOC(sub_pham,(nstates*(nstates+1)/2))
     970         1176 :  sub_pham=czero; ipack=0
     971              : 
     972          231 :  do jj=1,nstates
     973        80850 :    hphi_tot = czero
     974    124024530 :    hphi_tot(:) = MATMUL(hexc, phi_block(:,jj))
     975          210 :    call xmpi_sum(hphi_tot,comm,ierr)
     976              : 
     977         1386 :    do ii=1,jj
     978         1155 :      ipack=ipack+1
     979       444675 :      sub_pham(ipack) = DOT_PRODUCT(phi_block(my_t1:my_t2,ii), hphi_tot(my_t1:my_t2) )
     980         1365 :      if (ii==jj) sub_pham(ipack) = REAL(sub_pham(ipack),kind=dp)
     981              :    end do
     982              :  end do
     983           21 :  call xmpi_sum(sub_pham,comm,ierr)
     984              : 
     985           84 :  ABI_MALLOC(sub_ham,(nstates,nstates))
     986         2331 :  sub_ham=czero
     987           63 :  ABI_MALLOC(sub_ene,(nstates))
     988              : 
     989           21 :  call xhpev("Vectors","Upper",nstates,sub_pham,sub_ene,sub_ham,nstates) !,comm)
     990              : 
     991           21 :  ABI_FREE(hphi_tot)
     992           21 :  ABI_FREE(sub_pham)
     993           21 :  ABI_FREE(sub_ene)
     994              : 
     995              :  !do ii=1,nstates
     996              :  ! norm = DOT_PRODUCT(sub_ham(:,ii),sub_ham(:,ii))
     997              :  ! write(std_out,*)"norm subspac",norm
     998              :  ! sub_ham(:,ii) = sub_ham(:,ii)/norm
     999              :  !end do
    1000              : 
    1001              :  !allocate(evec(2*nstates,nstates))
    1002              : 
    1003              :  !do ii=1,nstates
    1004              :  ! do jj=1,nstates
    1005              :  ! evec(jj,  ii) = REAL (sub_ham(jj,ii))
    1006              :  ! evec(jj+1,ii) = AIMAG(sub_ham(jj,ii))
    1007              :  ! end do
    1008              :  !end do
    1009              : 
    1010              :  !call normev(evec,nstates,nstates)
    1011              : 
    1012              :  !do ii=1,nstates
    1013              :  ! do jj=1,nstates
    1014              :  !  sub_ham(jj,ii) = CMPLX( evec(jj,ii),evec(jj+1,ii) )
    1015              :  ! end do
    1016              :  !end do
    1017              :  !deallocate(evec)
    1018              : 
    1019              : #if 0
    1020              :  ABI_MALLOC(phi_tmp,(my_nt,nstates))
    1021              :  phi_tmp = phi_block
    1022              : 
    1023              :  call ZGEMM('N','N',my_nt,nstates,nstates,cone,phi_tmp,my_nt,sub_ham,nstates,czero,phi_block,my_nt)
    1024              : 
    1025              :  ABI_FREE(phi_tmp)
    1026              : #else
    1027       161784 :  phi_block = MATMUL(phi_block,sub_ham)
    1028              : #endif
    1029              : 
    1030           21 :  ABI_FREE(sub_ham)
    1031              : 
    1032           21 : end subroutine exc_subspace_rotation
    1033              : !!***
    1034              : 
    1035              : !----------------------------------------------------------------------
    1036              : 
    1037              : !!****f* m_exc_itdiago/exc_cholesky_ortho
    1038              : !! NAME
    1039              : !! exc_cholesky_ortho
    1040              : !!
    1041              : !! FUNCTION
    1042              : !!  This routine performs the orthogonalization of the trial eigenstates using the
    1043              : !!  Cholesky Algorithm.
    1044              : !!
    1045              : !! SIDE EFFECTS
    1046              : !!   phi_block(my_t1:my_t2,nstates)=Contains the trial eigenstates.
    1047              : !!
    1048              : !! SOURCE
    1049              : 
    1050           21 : subroutine exc_cholesky_ortho()
    1051              : 
    1052              : !Local variables ------------------------------
    1053              :  integer :: my_info,ii,jj,ipack,ierr
    1054              :  logical,parameter :: use_unpacked = .False.
    1055              : !arrays
    1056           21 :  complex(dp),allocatable :: overlap(:,:),povlp(:)
    1057              : !************************************************************************
    1058              : 
    1059              :  ! 1) overlap_ij =  <phi_i|phi_j>
    1060           84 :  ABI_MALLOC(overlap, (nstates,nstates))
    1061              : 
    1062              :  if (use_unpacked) then
    1063              :    overlap = czero
    1064              : 
    1065              :    call ZGEMM('C','N',nstates,nstates,my_nt,cone,phi_block,my_nt,phi_block,my_nt,czero,overlap,nstates)
    1066              :    call xmpi_sum(overlap,comm,ierr)
    1067              : 
    1068              :    do ii=1,nstates
    1069              :      overlap(ii,ii)=REAL(overlap(ii,ii),kind=dp)
    1070              :    end do
    1071              : 
    1072              :    ! 2) Cholesky factorization: overlap = U^H U with U upper triangle matrix.
    1073              :    call ZPOTRF('U',nstates,overlap,nstates,my_info)
    1074              :    if (my_info/=0)  then
    1075              :      write(msg,'(a,i3)')' ZPOTRF returned info= ',my_info
    1076              :      ABI_ERROR(msg)
    1077              :    end if
    1078              : 
    1079              :  else
    1080              :    ! 1) Calculate overlap_ij =  <phi_i|phi_j> in packed form.
    1081           63 :    ABI_MALLOC(povlp,(nstates*(nstates+1)/2))
    1082         1176 :    povlp = czero; ipack=0
    1083          231 :    do jj=1,nstates
    1084         1386 :      do ii=1,jj
    1085         1155 :        ipack=ipack+1
    1086       444675 :        povlp(ipack) = DOT_PRODUCT( phi_block(my_t1:my_t2,ii), phi_block(my_t1:my_t2,jj) )
    1087         1365 :        if (ii==jj) povlp(ipack) = REAL(povlp(ipack),kind=dp)
    1088              :      end do
    1089              :    end do
    1090           21 :    call xmpi_sum(povlp,comm,ierr)
    1091              : 
    1092              :    ! 2) Cholesky factorization: overlap = U^H U with U upper triangle matrix.
    1093           21 :    call ZPPTRF("U",nstates,povlp,my_info)
    1094           21 :    if (my_info/=0)  then
    1095            0 :      write(msg,'(a,i3)')' ZPPTRF returned info= ',my_info
    1096            0 :      ABI_ERROR(msg)
    1097              :    end if
    1098              :    !call xmpi_sum(povlp,comm,ierr)
    1099              :    !povlp=povlp/nproc
    1100              : 
    1101              :    !unpack povlp to prepare call to ZTRSM.
    1102           21 :    ipack=0
    1103          231 :    do jj=1,nstates
    1104         1386 :      do ii=1,jj
    1105         1155 :        ipack=ipack+1
    1106         1365 :        if (ii/=jj) then
    1107          945 :          overlap(ii,jj)=      povlp(ipack)
    1108          945 :          overlap(jj,ii)=CONJG(povlp(ipack))
    1109              :        else
    1110          210 :          overlap(ii,ii)=REAL(povlp(ipack),kind=dp)
    1111              :        end if
    1112              :      end do
    1113              :    end do
    1114           42 :    ABI_FREE(povlp)
    1115              :  end if
    1116              : 
    1117              :  ! Check if this can be done with Scalapack. Direct PZTRSM is not provided
    1118              : 
    1119              :  ! 3) Solve X U = phi_block, on exit the phi_block treated by this node is orthonormalized.
    1120              :  !call ZTRSM('R','U','N','N',hexc_size,nstates,cone,overlap,nstates,phi_block,hexc_size)
    1121           21 :  call ZTRSM('Right','Upper','Normal','Normal',my_nt,nstates,cone,overlap,nstates,phi_block,my_nt)
    1122           21 :  ABI_FREE(overlap)
    1123              : 
    1124           21 : end subroutine exc_cholesky_ortho
    1125              : !!***
    1126              : 
    1127              : !----------------------------------------------------------------------
    1128              : 
    1129              : !!****f* m_exc_itdiago/convergence_degree
    1130              : !! NAME
    1131              : !! convergence_degree
    1132              : !!
    1133              : !! FUNCTION
    1134              : !!  Return the degree of convergence from the input residual.
    1135              : !!
    1136              : !! INPUTS
    1137              : !!  resid=Residual.
    1138              : !!
    1139              : !! OUTPUT
    1140              : !!
    1141              : !! SOURCE
    1142              : 
    1143          736 : function convergence_degree(resid)
    1144              : 
    1145              : !Arguments
    1146              :  integer :: convergence_degree
    1147              :  real(dp),intent(in) :: resid
    1148              : 
    1149              : !************************************************************************
    1150              : 
    1151          736 :  if (resid<tolwfr_) then
    1152              :    convergence_degree = STRICT
    1153              :  else
    1154          713 :    convergence_degree = WORST
    1155          713 :    if (resid<tolwfr_*10**5) convergence_degree = MEDIUM
    1156              :  end if
    1157              : 
    1158              : end function convergence_degree
    1159              : !!***
    1160              : 
    1161              : !----------------------------------------------------------------------
    1162              : 
    1163              : !!****f* m_exc_itdiago/exc_check_phi_block
    1164              : !! NAME
    1165              : !! exc_check_phi_block
    1166              : !!
    1167              : !! FUNCTION
    1168              : !!  Debugging tools
    1169              : !!
    1170              : !! INPUTS
    1171              : !!
    1172              : !! OUTPUT
    1173              : !!
    1174              : !! SOURCE
    1175              : 
    1176              : subroutine exc_check_phi_block(string)
    1177              : 
    1178              : !Arguments ------------------------------------
    1179              : !scalars
    1180              :  character(len=*),intent(in) :: string
    1181              : 
    1182              : !Local variables ------------------------------
    1183              : !scalars
    1184              :  integer :: ii,jj,ierr
    1185              :  real(dp) :: err,rdum
    1186              : !arrays
    1187           22 :  complex(dp),allocatable :: lbuff(:,:)
    1188              : !************************************************************************
    1189              : 
    1190              :  if (.not. DEBUGME) return
    1191              : 
    1192              : #if 0
    1193              :  ABI_MALLOC(lbuff,(hexc_size,nstates))
    1194              :  err = -one
    1195              :  do irank=1,nproc-1
    1196              :    call xmpi_exch(phi_block,hexc_size*nstates,irank,lbuff,master,comm,11,ierr)
    1197              :    if (my_rank==master) then
    1198              :      lbuff = lbuff-phi_block
    1199              :      err = MAX(err,MAXVAL(MAXVAL(ABS(lbuff),DIM=1)))
    1200              :    end if
    1201              :    call xmpi_barrier(comm)
    1202              :  end do
    1203              :  ABI_FREE(lbuff)
    1204              : #else
    1205              : 
    1206              :  ABI_MALLOC(lbuff,(nstates,nstates))
    1207              :  lbuff=czero
    1208              :  do jj=1,nstates
    1209              :    do ii=1,jj
    1210              :      lbuff(ii,jj) = DOT_PRODUCT( phi_block(my_t1:my_t2,ii), phi_block(my_t1:my_t2,jj) )
    1211              :    end do
    1212              :  end do
    1213              :  call xmpi_sum(lbuff,comm,ierr)
    1214              : 
    1215              :  err = -one
    1216              :  do jj=1,nstates
    1217              :    do ii=1,jj
    1218              :      if (ii==jj) then
    1219              :        rdum =  ABS(lbuff(ii,jj)-one)
    1220              :      else
    1221              :        rdum =  ABS(lbuff(ii,jj))
    1222              :      end if
    1223              :      err = MAX(err,rdum)
    1224              :    end do
    1225              :  end do
    1226              :  ABI_FREE(lbuff)
    1227              : #endif
    1228              : 
    1229              :  if (my_rank==master) then
    1230              :    write(std_out,*)"After ",TRIM(string),", MAX inconsistency error in phi_block= ",err
    1231              :  end if
    1232              : 
    1233              :  !write(std_out,*)"master casts its own data"
    1234              :  !call xmpi_bcast(phi_block,master,comm,ierr)
    1235              : 
    1236              : end subroutine exc_check_phi_block
    1237              : !!***
    1238              : 
    1239              : !----------------------------------------------------------------------
    1240              : 
    1241              : end subroutine exc_iterative_diago
    1242              : !!***
    1243              : 
    1244              : end module m_exc_itdiago
    1245              : !!***
        

Generated by: LCOV version 2.3-1