program test_fio

  use mpi
  use wdfile
  use h5file
  
  implicit none   

  ! args
  integer                :: narg, cptArg   
  logical                :: io_hdf5=.FALSE.
  
  integer, parameter     :: dim = 3
  integer, parameter     :: factor = 1
  integer, parameter     :: nx = 256 * factor
  integer, parameter     :: ny = 256 * factor
  integer, parameter     :: nz = 256 * factor
  integer, parameter     :: numrep = 100
  integer, parameter     :: iounit = 27
  integer, parameter     :: mib = 1024*1024
  
  integer :: rank, size, ierr, comm
  integer :: stat
  integer :: i, j, k, l
  
  character(len=100) :: filename, name
  double precision, asynchronous   :: data(0:nx, 0:ny, 0:nz)
  double precision   :: ti, tf, etime, data_proc, total_data
  double precision   :: iorate, max_iorate, mean_iorate
  double precision   :: min_time, mean_time  
  
  call MPI_Init(ierr)
  comm = MPI_COMM_WORLD
  
  call MPI_Comm_size(comm, size, ierr)
  call MPI_Comm_rank(comm, rank, ierr)

  data_proc  = float(sizeof(1.d0)*nx*ny*nz)/float(mib)
  total_data = float(sizeof(1.d0)*nx*ny*nz)*float(size)/float(mib)

  ! Take  arguments for hdf5
  narg = command_argument_count()
  if (narg > 0) then  
     do cptArg = 1,narg
        call get_command_argument(cptArg,name)
        select case(adjustl(name))
        case("--help","-h")
           write(*,*)"./fio  [--hdf5] (fortran is default IO) "
           stop
        case("--hdf5") 
           io_hdf5=.TRUE.
        end select
     end do
  end if

  
  if (rank == 0) then
     write(*,*)
     write(*,*) 'Fortran IO test             '
     write(*,*) '----------------------------'
     write(*,*)
     write(*,*) 'Using ', size, ' process(es)'
     write(*,*) 'Matrix size is   (', nx, ', ', ny, ', ', nz, ')'
     write(*,*)
     write(*,*) 'Data / process = ', data_proc, ' MiB'
     write(*,*) 'Total amount of data written = ', total_data, ' MiB'
     write(*,*)
     if (io_hdf5) then
        write(*,*) 'HDF5 IO used'        
     else
        write(*,*) 'Fortran IO used'                
     end if
     write(*,*)     
  endif


  
  ! repeat io tests
  do  l=1, numrep

     call MPI_Barrier(comm, ierr)
     if (rank == 0) then
        ti = MPI_Wtime()
     end if
 
     ! reset array   
     data(:,:,:) = -1
     
     ! fill dummy data
     do i = 1, nx
        do j = 1, ny
           do k = 1, nz
              data(i,j,k) = (i+j+k) * 0.1              
           end do
        end do
     end do
     
    filename = 'data_'//trim(str(l))//'_'


    if (io_hdf5) then
       ! hdf5 IO
       call h5write( filename, data, nx, ny, nz, comm)
    else
       ! fortran pure IO
       call fwrite( filename, data, nx, ny, nz, comm)       
    end if
    
    call MPI_Barrier(comm, ierr)

     if (rank == 0) then
        tf = MPI_Wtime()
        etime = tf - ti
        iorate = total_data/etime

        mean_time = mean_time + etime/numrep
        mean_iorate = mean_iorate + iorate/numrep
        
        if (max_iorate < iorate) then
           max_iorate = iorate
           min_time = etime
        end if
        
        write(*,*) 'time = ', etime, ', rate = ', iorate, ' MiB/s'
     end if

     
     if (io_hdf5) then
        call h5delete(filename,comm)      
     else
        call fdelete(filename,comm)      
     end if     

 end do

 if (rank == 0) then
    write(*,*)
    write(*,*) 'min_time = ', min_time, ', max_rate = ', max_iorate, ' MiB/s'
    write(*,*) 'mean_time = ', mean_time, ', mean_rate = ', mean_iorate, ' MiB/s'
    write(*,*)
 end if


  if (rank == 0) then
     write(*,*)
     write(*,*) '-----------------------'
     write(*,*) 'Fortan IO test finished'
     write(*,*) '-----------------------'
     write(*,*)
  end if

  call MPI_Finalize(ierr)
 
 
end program test_fio
