!=========================================================================
!
! Utilities:
!
! (1) epsmat_converter     Originally by DVF      Last Modified 09/20/2013 (DVF)
!
!     This utility converts epsmat files from the old epsilon format to
!     the new HDF5 format, to facilitate people switching to HDF5.
!
!=========================================================================

#include "f_defs.h"

program epsmat_converter

  use global_m
  use hdf5
  use write_matrix_m
  use epswrite_hdf5_m

  implicit none
  
  character :: ajname*6,adate*11,outfile*80,infile*80
  real(DP)  :: ecuts,qk(3)
  real(DP), allocatable :: dFreqGrid(:), epsdiag(:,:,:),ekin(:),qpts(:,:)
  complex(DPC), allocatable :: dFreqBrd(:),epsRDyn(:,:,:),epsADyn(:,:,:)
  integer   :: ig,ng,ngq, ii,iq,qgrid(3),freq_dep,nFreq, &
    nq, nq_file,nmtxmax,isize,jj,ifreq,error
  SCALAR, allocatable :: eps(:,:)
  integer, allocatable :: isort(:),isorti(:),gcomponents(:,:),nmtx0_of_q(:),nmtx0_of_q_file(:)
  
  write(6,*) MYFLAVOR // ' version is used to convert old epsmat format to hdf5 format'

  call h5open_f(error)
  
!------------------
! DVF : get gvector & qpoint information from input file, and the input/output file names
! Want number of gvectors so that we can read in g-vector components before the call
! to write the hdf5 epsmat header - call eps_hdf5_setup
! Want number of qpoints so that we can read in nmtx0_of_q. We want to read in this
! array because otherwise we`d have to read get it from the file by looping through
! the whole file, which can take a long time for big files

  call open_file(unit=10,file='epsmat_old2hdf5.inp',form='formatted',status='old')
  read(10,*) infile
  read(10,*) outfile
  read(10,*) nq
  close(10)

  SAFE_ALLOCATE(qpts,(3,nq))
  SAFE_ALLOCATE(nmtx0_of_q,(nq))
  SAFE_ALLOCATE(nmtx0_of_q_file,(nq))
  SAFE_ALLOCATE(gcomponents, (3,ng))

  nmtxmax=0

!--------------------------
!  Read in the epsmat file
!
  call open_file(unit=11,file=TRUNC(infile),form='unformatted',status='old')
  read(11) ajname,adate
  read(11) freq_dep,nFreq
  read(11) (qgrid(ii),ii=1,3)
  if (freq_dep .eq. 2) then
    SAFE_ALLOCATE(dFreqGrid,(nFreq))
    SAFE_ALLOCATE(dFreqBrd,(nFreq))
    read(11) (dFreqGrid(ii),ii=1,nFreq),(dFreqBrd(ii),ii=1,nFreq)
  else
    read(11)
  endif
  read(11)
  read(11)
  read(11) ecuts
  read(11) nq_file,((qpts(jj,iq),jj=1,3),iq=1,nq)
  if(nq_file .ne. nq) then
    call die('Number of qpoints in input file not the same as what is in epsmat file')
  endif
  read(11) ng
  do iq=1,nq
    read(11) ngq,nmtx0_of_q(iq)
    if(nmtx0_of_q(iq) .gt. nmtxmax) then
      nmtxmax=nmtx0_of_q(iq)
    endif
    read(11)
    read(11)
    if (freq_dep .eq. 2) then    
      do jj = 1, nmtx0_of_q(iq)
        do ii = 1, nmtx0_of_q(iq)
          read(11)
        enddo
#ifdef CPLX
        do ii = 1, nmtx0_of_q(iq)
          read(11)
        enddo
#endif
      enddo
    else
      do jj = 1, nmtx0_of_q(iq)
        read(11)
      enddo
    endif
  enddo

! JRD - LETS READ the nmtx here... Putting it in .inp is too much to ask user

  call close_file(11)

  SAFE_ALLOCATE(isort, (ng))  
  SAFE_ALLOCATE(isorti, (ng)) 
  SAFE_ALLOCATE(ekin, (ng))   
                              
! Write header for hdf5 file

! Read body of epsmat from old format and write to hdf5 file

  call open_file(unit=11,file=TRUNC(infile),form='unformatted',status='old')
  read(11)
  read(11)
  read(11)
  read(11)
  read(11)
  read(11)
  read(11)
  read(11) nq
  read(11) ng,((gcomponents(jj,ig),jj=1,3),ig=1,ng)

  call eps_hdf5_setup(freq_dep,nFreq,dFreqGrid,dFreqBrd,ecuts,&
    qgrid,ng,gcomponents,nq,qpts,nmtx0_of_q,nmtxmax,1,outfile)

  SAFE_DEALLOCATE(dFreqBrd)
  SAFE_DEALLOCATE(dFreqGrid)

  do iq=1,nq
    write(*,*) "iq",iq
    if(freq_dep .eq. 2) then
      SAFE_ALLOCATE(epsRDyn, (nFreq,nmtx0_of_q(iq),nmtx0_of_q(iq)))
#ifdef CPLX
      SAFE_ALLOCATE(epsADyn, (nFreq,nmtx0_of_q(iq),nmtx0_of_q(iq)))
#endif 
    else
      SAFE_ALLOCATE(eps, (nmtx0_of_q(iq),nmtx0_of_q(iq))) 
    endif
    read(11) ngq,nmtx0_of_q_file(iq),(isort(ig),isorti(ig),ig=1,ngq)
    if(nmtx0_of_q_file(iq) .ne. nmtx0_of_q(iq)) then
      call die('nmtx0_of_q in input file not the same as what is in epsmat file')
    endif
    read(11) (ekin(ig),ig=1,ngq)
    read(11) (qk(jj),jj=1,3)
    if (freq_dep .eq. 2) then    
      do jj = 1, nmtx0_of_q(iq)
        do ii = 1, nmtx0_of_q(iq)
          read(11) (epsRDyn(ifreq, ii, jj), ifreq= 1, nFreq)
        enddo
#ifdef CPLX
        do ii = 1, nmtx0_of_q(iq)
          read(11) (epsADyn(ifreq, ii, jj),ifreq = 1, nFreq)
        enddo
#endif
      enddo
    else
      do jj = 1, nmtx0_of_q(iq)
         read(11) (eps(ii,jj),ii=1,nmtx0_of_q(iq))
      enddo
    endif
    call write_gvec_indices_hdf(ng,isort,isorti,ekin,iq,outfile)

    isize=SCALARSIZE
    if(freq_dep .eq. 2) then
#ifdef CPLX
      call write_matrix_f_ser_hdf(nFreq,epsRDyn,epsADyn,nmtx0_of_q(iq),iq,1,outfile)
#else
      call write_matrix_f_ser_hdf(nFreq,epsRDyn,nmtx0_of_q(iq),iq,1,outfile)
#endif
    else
      call write_matrix_ser_hdf(eps,nmtx0_of_q(iq),iq,1,outfile)
    endif

    SAFE_ALLOCATE(epsdiag,(isize,nmtx0_of_q(iq),1))

    if (freq_dep .ne. 2) then
      do jj = 1, nmtx0_of_q(iq)
        epsdiag(1,jj,1) = dble(eps(jj,jj))
#ifdef CPLX
        epsdiag(2,jj,1) = IMAG(eps(jj,jj))
#endif
      enddo
    else
      do jj = 1, nmtx0_of_q(iq)
        epsdiag(1,jj,1) = dble(epsRDyn(1,jj,jj))
        epsdiag(2,jj,1) = IMAG(epsRDyn(2,jj,jj))
      enddo
    endif
    call write_matrix_diagonal_hdf(epsdiag,nmtx0_of_q(iq),iq,isize,outfile)

    SAFE_DEALLOCATE(epsdiag)
    if(freq_dep .eq. 2) then
      SAFE_DEALLOCATE(epsRDyn)
#ifdef CPLX
      SAFE_DEALLOCATE(epsADyn)
#endif 
    else
      SAFE_DEALLOCATE(eps)
    endif
  enddo

  call close_file(11)

end program epsmat_converter
