!===================================================
! DO NOT EDIT THIS FILE, it was generated using /glade/home/jedwards/fis/pio_trunk/pio/genf90.pl 
! Any changes you make to this file may be lost
!===================================================
#define __PIO_FILE__ "pionfread_mod.F90.in"
module pionfread_mod

  implicit none

  private
!> 
!! @private
!<
  public :: read_nf
# 11 "pionfread_mod.F90.in"
  interface read_nf
     ! TYPE real,double,int
     module procedure read_nfdarray_real
     ! TYPE real,double,int
     module procedure read_nfdarray_double
     ! TYPE real,double,int
     module procedure read_nfdarray_int
  end interface

  character(len=*), parameter :: modName='pionfread_mod'

# 18 "pionfread_mod.F90.in"
contains

  ! TYPE real,double,int
!>
!! @private
!<
# 24 "pionfread_mod.F90.in"
  integer function read_nfdarray_real (File,IOBUF,varDesc,IODesc, start,count) result(ierr)
    use pio_types, only : file_desc_t, var_desc_t, io_desc_t, pio_real, pio_double, pio_int, &
	pio_noerr, pio_iotype_netcdf4p, pio_iotype_netcdf4c, pio_iotype_pnetcdf, pio_iotype_netcdf, &
	pio_max_var_dims
    use pio_kinds, only : pio_offset, i4, r4, r8
    use pio_utils, only : check_netcdf, bad_iotype 
    use pio_support, only : Debug, DebugIO, piodie, checkmpireturn
    use alloc_mod, only: alloc_check
#ifdef _NETCDF
    use netcdf, only : nf90_get_var  !_EXTERNAL
#endif
#ifdef TIMING
    use perf_mod, only : t_startf, t_stopf  !_EXTERNAL
#endif
#ifndef NO_MPIMOD
    use mpi   !_EXTERNAL
#endif
    implicit none
#ifdef NO_MPIMOD
    include 'mpif.h'   !_EXTERNAL
#endif
#ifdef _PNETCDF
#include <pnetcdf.inc>   /* _EXTERNAL */
#endif

    type (File_desc_t), intent(inout) :: File
    real(r4), intent(inout)           :: IOBUF(:)
    type (Var_desc_t), intent(in) :: varDesc
    type (IO_desc_t), intent(in) :: IODesc
    integer(kind=pio_offset), intent(in) :: start(:), count(:)


    character(len=*), parameter :: subName=modName//'::read_nfdarray_real'
    integer(kind=i4) :: iotype

    integer :: iobuf_size, max_iobuf_size
    integer :: status(MPI_STATUS_SIZE)
    integer, dimension(PIO_MAX_VAR_DIMS) :: temp_start, temp_count
    integer :: i, mpierr, ndims, sdims

#ifdef TIMING
    call t_startf("pio_read_nfdarray_real")
#endif
    iotype = File%iotype
    ierr=PIO_noerr


    ndims = size(start)
    if (File%iosystem%IOproc) then
       select case (iotype) 
#ifdef _PNETCDF
       case(pio_iotype_pnetcdf)
          if(DebugIO) print *,__PIO_FILE__,__LINE__, &
               '  IAM: ',File%iosystem%io_rank

          if(Debug) print *,__PIO_FILE__,__LINE__, &
               '  IAM: ',File%iosystem%io_rank,' start: ', &
               start,' count: ', &
               count, ' iobuf size: ',size(iobuf)

          ierr=nfmpi_get_vara_all( File%fh,varDesc%varid, &
               start, &
               count, &
               IOBUF,iodesc%Read%n_ElemTYPE, &
               iodesc%Read%ElemTYPE)
#endif

#ifdef _NETCDF
       case(pio_iotype_netcdf4p, pio_iotype_netcdf4c)	
! all reads can be parallel in netcdf4 format
          ierr= nf90_get_var(File%fh, vardesc%varid, iobuf, start=int(start),count=int(count))
       case(pio_iotype_netcdf)
          iobuf_size=size(IOBUF)
          call MPI_REDUCE( iobuf_size,max_iobuf_size, &
               1,MPI_INTEGER,MPI_MAX,0,File%iosystem%IO_comm,mpierr )
          call checkmpireturn(subName, mpierr)

          if (File%iosystem%io_rank==0) then
             if (max_iobuf_size > iobuf_size) then
                print *, 'IOBUF on root is not big enough', max_iobuf_size, iobuf_size
                call abort
             endif
          endif

          ! create temporaries of size int (netcdf limitation)
	 
	  temp_start=1
	  temp_count=1
          if (File%iosystem%io_rank>0) then
             temp_start(1:ndims)=start(1:ndims)
             temp_count(1:ndims)=count(1:ndims)

             if (Debug) print *, File%iosystem%comp_rank,': waiting to receive IOBUF', start, count

             call MPI_SEND( temp_start,ndims,MPI_INTEGER, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,mpierr )
             call checkmpireturn(subName, mpierr)

             call MPI_SEND( temp_count,ndims,MPI_INTEGER, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,mpierr )
             call checkmpireturn(subName, mpierr)

             call MPI_SEND( iobuf_size,1,MPI_INTEGER, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,mpierr )
             call checkmpireturn(subName, mpierr)

             call MPI_RECV( IOBUF,size(IOBUF), &
                  MPI_REAL4, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,status,mpierr )
             call checkmpireturn(subName, mpierr)

             if (Debug) print *, subName,':: comp_rank: ',File%iosystem%comp_rank, &
                  ': received IOBUF size=',size(IOBUF)
          endif

          ! Read rank>0 first then go back and read 0
          ! so that we can re-use the rank 0 IOBUF

          if (File%iosystem%io_rank==0) then
             do i=1,File%iosystem%num_iotasks-1
                if (Debug) print *, subName,': 0: reading netcdf for ',i

                call MPI_RECV( temp_start, ndims, MPI_INTEGER, &
                     i,i,File%iosystem%IO_comm,status,mpierr)
                call CheckMPIReturn('read_nfdarray_real',mpierr)

                call MPI_RECV( temp_count, ndims, MPI_INTEGER, &
                     i,i,File%iosystem%IO_comm,status,mpierr)
                call CheckMPIReturn('read_nfdarray_real',mpierr)

                call MPI_RECV( iobuf_size, 1, MPI_INTEGER,    &
                     i,i,File%iosystem%IO_comm,status,mpierr)
                call CheckMPIReturn('read_nfdarray_real',mpierr)

                ierr=nf90_get_var( File%fh, varDesc%varid, &
                     IOBUF, temp_start(1:ndims), temp_count(1:ndims) )

                call MPI_SEND( IOBUF,iobuf_size, &
                     MPI_REAL4, &
                     i,i,File%iosystem%IO_comm,mpierr)
                call CheckMPIReturn('read_nfdarray_real',mpierr)

                if (Debug) print *, subName,': 0: done reading netcdf for ',i
             end do ! i=1,File%iosystem%num_iotasks-1

             ! Read root data last

             if (Debug) print *, subName,': 0: reading netcdf for self', vardesc%varid, ndims, start, count

             temp_start(1:ndims)=start(1:ndims)
             temp_count(1:ndims)=count(1:ndims)

             ierr=nf90_get_var( File%fh, varDesc%varid, &
                  IOBUF, temp_start(1:ndims), temp_count(1:ndims) )

             if (Debug) print *, subName,': 0: done reading netcdf for self'

          endif ! File%iosystem%io_rank==0

#endif

       case default
          call bad_iotype(iotype,__PIO_FILE__,__LINE__)

       end select
    endif ! File%iosystem%IOproc
    call check_netcdf(File, ierr,__PIO_FILE__,__LINE__);
#ifdef TIMING
    call t_stopf("pio_read_nfdarray_real")
#endif

  end function read_nfdarray_real

  ! TYPE real,double,int
!>
!! @private
!<
# 24 "pionfread_mod.F90.in"
  integer function read_nfdarray_double (File,IOBUF,varDesc,IODesc, start,count) result(ierr)
    use pio_types, only : file_desc_t, var_desc_t, io_desc_t, pio_real, pio_double, pio_int, &
	pio_noerr, pio_iotype_netcdf4p, pio_iotype_netcdf4c, pio_iotype_pnetcdf, pio_iotype_netcdf, &
	pio_max_var_dims
    use pio_kinds, only : pio_offset, i4, r4, r8
    use pio_utils, only : check_netcdf, bad_iotype 
    use pio_support, only : Debug, DebugIO, piodie, checkmpireturn
    use alloc_mod, only: alloc_check
#ifdef _NETCDF
    use netcdf, only : nf90_get_var  !_EXTERNAL
#endif
#ifdef TIMING
    use perf_mod, only : t_startf, t_stopf  !_EXTERNAL
#endif
#ifndef NO_MPIMOD
    use mpi   !_EXTERNAL
#endif
    implicit none
#ifdef NO_MPIMOD
    include 'mpif.h'   !_EXTERNAL
#endif
#ifdef _PNETCDF
#include <pnetcdf.inc>   /* _EXTERNAL */
#endif

    type (File_desc_t), intent(inout) :: File
    real(r8), intent(inout)           :: IOBUF(:)
    type (Var_desc_t), intent(in) :: varDesc
    type (IO_desc_t), intent(in) :: IODesc
    integer(kind=pio_offset), intent(in) :: start(:), count(:)


    character(len=*), parameter :: subName=modName//'::read_nfdarray_double'
    integer(kind=i4) :: iotype

    integer :: iobuf_size, max_iobuf_size
    integer :: status(MPI_STATUS_SIZE)
    integer, dimension(PIO_MAX_VAR_DIMS) :: temp_start, temp_count
    integer :: i, mpierr, ndims, sdims

#ifdef TIMING
    call t_startf("pio_read_nfdarray_double")
#endif
    iotype = File%iotype
    ierr=PIO_noerr


    ndims = size(start)
    if (File%iosystem%IOproc) then
       select case (iotype) 
#ifdef _PNETCDF
       case(pio_iotype_pnetcdf)
          if(DebugIO) print *,__PIO_FILE__,__LINE__, &
               '  IAM: ',File%iosystem%io_rank

          if(Debug) print *,__PIO_FILE__,__LINE__, &
               '  IAM: ',File%iosystem%io_rank,' start: ', &
               start,' count: ', &
               count, ' iobuf size: ',size(iobuf)

          ierr=nfmpi_get_vara_all( File%fh,varDesc%varid, &
               start, &
               count, &
               IOBUF,iodesc%Read%n_ElemTYPE, &
               iodesc%Read%ElemTYPE)
#endif

#ifdef _NETCDF
       case(pio_iotype_netcdf4p, pio_iotype_netcdf4c)	
! all reads can be parallel in netcdf4 format
          ierr= nf90_get_var(File%fh, vardesc%varid, iobuf, start=int(start),count=int(count))
       case(pio_iotype_netcdf)
          iobuf_size=size(IOBUF)
          call MPI_REDUCE( iobuf_size,max_iobuf_size, &
               1,MPI_INTEGER,MPI_MAX,0,File%iosystem%IO_comm,mpierr )
          call checkmpireturn(subName, mpierr)

          if (File%iosystem%io_rank==0) then
             if (max_iobuf_size > iobuf_size) then
                print *, 'IOBUF on root is not big enough', max_iobuf_size, iobuf_size
                call abort
             endif
          endif

          ! create temporaries of size int (netcdf limitation)
	 
	  temp_start=1
	  temp_count=1
          if (File%iosystem%io_rank>0) then
             temp_start(1:ndims)=start(1:ndims)
             temp_count(1:ndims)=count(1:ndims)

             if (Debug) print *, File%iosystem%comp_rank,': waiting to receive IOBUF', start, count

             call MPI_SEND( temp_start,ndims,MPI_INTEGER, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,mpierr )
             call checkmpireturn(subName, mpierr)

             call MPI_SEND( temp_count,ndims,MPI_INTEGER, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,mpierr )
             call checkmpireturn(subName, mpierr)

             call MPI_SEND( iobuf_size,1,MPI_INTEGER, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,mpierr )
             call checkmpireturn(subName, mpierr)

             call MPI_RECV( IOBUF,size(IOBUF), &
                  MPI_REAL8, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,status,mpierr )
             call checkmpireturn(subName, mpierr)

             if (Debug) print *, subName,':: comp_rank: ',File%iosystem%comp_rank, &
                  ': received IOBUF size=',size(IOBUF)
          endif

          ! Read rank>0 first then go back and read 0
          ! so that we can re-use the rank 0 IOBUF

          if (File%iosystem%io_rank==0) then
             do i=1,File%iosystem%num_iotasks-1
                if (Debug) print *, subName,': 0: reading netcdf for ',i

                call MPI_RECV( temp_start, ndims, MPI_INTEGER, &
                     i,i,File%iosystem%IO_comm,status,mpierr)
                call CheckMPIReturn('read_nfdarray_double',mpierr)

                call MPI_RECV( temp_count, ndims, MPI_INTEGER, &
                     i,i,File%iosystem%IO_comm,status,mpierr)
                call CheckMPIReturn('read_nfdarray_double',mpierr)

                call MPI_RECV( iobuf_size, 1, MPI_INTEGER,    &
                     i,i,File%iosystem%IO_comm,status,mpierr)
                call CheckMPIReturn('read_nfdarray_double',mpierr)

                ierr=nf90_get_var( File%fh, varDesc%varid, &
                     IOBUF, temp_start(1:ndims), temp_count(1:ndims) )

                call MPI_SEND( IOBUF,iobuf_size, &
                     MPI_REAL8, &
                     i,i,File%iosystem%IO_comm,mpierr)
                call CheckMPIReturn('read_nfdarray_double',mpierr)

                if (Debug) print *, subName,': 0: done reading netcdf for ',i
             end do ! i=1,File%iosystem%num_iotasks-1

             ! Read root data last

             if (Debug) print *, subName,': 0: reading netcdf for self', vardesc%varid, ndims, start, count

             temp_start(1:ndims)=start(1:ndims)
             temp_count(1:ndims)=count(1:ndims)

             ierr=nf90_get_var( File%fh, varDesc%varid, &
                  IOBUF, temp_start(1:ndims), temp_count(1:ndims) )

             if (Debug) print *, subName,': 0: done reading netcdf for self'

          endif ! File%iosystem%io_rank==0

#endif

       case default
          call bad_iotype(iotype,__PIO_FILE__,__LINE__)

       end select
    endif ! File%iosystem%IOproc
    call check_netcdf(File, ierr,__PIO_FILE__,__LINE__);
#ifdef TIMING
    call t_stopf("pio_read_nfdarray_double")
#endif

  end function read_nfdarray_double

  ! TYPE real,double,int
!>
!! @private
!<
# 24 "pionfread_mod.F90.in"
  integer function read_nfdarray_int (File,IOBUF,varDesc,IODesc, start,count) result(ierr)
    use pio_types, only : file_desc_t, var_desc_t, io_desc_t, pio_real, pio_double, pio_int, &
	pio_noerr, pio_iotype_netcdf4p, pio_iotype_netcdf4c, pio_iotype_pnetcdf, pio_iotype_netcdf, &
	pio_max_var_dims
    use pio_kinds, only : pio_offset, i4, r4, r8
    use pio_utils, only : check_netcdf, bad_iotype 
    use pio_support, only : Debug, DebugIO, piodie, checkmpireturn
    use alloc_mod, only: alloc_check
#ifdef _NETCDF
    use netcdf, only : nf90_get_var  !_EXTERNAL
#endif
#ifdef TIMING
    use perf_mod, only : t_startf, t_stopf  !_EXTERNAL
#endif
#ifndef NO_MPIMOD
    use mpi   !_EXTERNAL
#endif
    implicit none
#ifdef NO_MPIMOD
    include 'mpif.h'   !_EXTERNAL
#endif
#ifdef _PNETCDF
#include <pnetcdf.inc>   /* _EXTERNAL */
#endif

    type (File_desc_t), intent(inout) :: File
    integer(i4), intent(inout)           :: IOBUF(:)
    type (Var_desc_t), intent(in) :: varDesc
    type (IO_desc_t), intent(in) :: IODesc
    integer(kind=pio_offset), intent(in) :: start(:), count(:)


    character(len=*), parameter :: subName=modName//'::read_nfdarray_int'
    integer(kind=i4) :: iotype

    integer :: iobuf_size, max_iobuf_size
    integer :: status(MPI_STATUS_SIZE)
    integer, dimension(PIO_MAX_VAR_DIMS) :: temp_start, temp_count
    integer :: i, mpierr, ndims, sdims

#ifdef TIMING
    call t_startf("pio_read_nfdarray_int")
#endif
    iotype = File%iotype
    ierr=PIO_noerr


    ndims = size(start)
    if (File%iosystem%IOproc) then
       select case (iotype) 
#ifdef _PNETCDF
       case(pio_iotype_pnetcdf)
          if(DebugIO) print *,__PIO_FILE__,__LINE__, &
               '  IAM: ',File%iosystem%io_rank

          if(Debug) print *,__PIO_FILE__,__LINE__, &
               '  IAM: ',File%iosystem%io_rank,' start: ', &
               start,' count: ', &
               count, ' iobuf size: ',size(iobuf)

          ierr=nfmpi_get_vara_all( File%fh,varDesc%varid, &
               start, &
               count, &
               IOBUF,iodesc%Read%n_ElemTYPE, &
               iodesc%Read%ElemTYPE)
#endif

#ifdef _NETCDF
       case(pio_iotype_netcdf4p, pio_iotype_netcdf4c)	
! all reads can be parallel in netcdf4 format
          ierr= nf90_get_var(File%fh, vardesc%varid, iobuf, start=int(start),count=int(count))
       case(pio_iotype_netcdf)
          iobuf_size=size(IOBUF)
          call MPI_REDUCE( iobuf_size,max_iobuf_size, &
               1,MPI_INTEGER,MPI_MAX,0,File%iosystem%IO_comm,mpierr )
          call checkmpireturn(subName, mpierr)

          if (File%iosystem%io_rank==0) then
             if (max_iobuf_size > iobuf_size) then
                print *, 'IOBUF on root is not big enough', max_iobuf_size, iobuf_size
                call abort
             endif
          endif

          ! create temporaries of size int (netcdf limitation)
	 
	  temp_start=1
	  temp_count=1
          if (File%iosystem%io_rank>0) then
             temp_start(1:ndims)=start(1:ndims)
             temp_count(1:ndims)=count(1:ndims)

             if (Debug) print *, File%iosystem%comp_rank,': waiting to receive IOBUF', start, count

             call MPI_SEND( temp_start,ndims,MPI_INTEGER, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,mpierr )
             call checkmpireturn(subName, mpierr)

             call MPI_SEND( temp_count,ndims,MPI_INTEGER, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,mpierr )
             call checkmpireturn(subName, mpierr)

             call MPI_SEND( iobuf_size,1,MPI_INTEGER, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,mpierr )
             call checkmpireturn(subName, mpierr)

             call MPI_RECV( IOBUF,size(IOBUF), &
                  MPI_INTEGER, &
                  0,File%iosystem%io_rank,File%iosystem%IO_comm,status,mpierr )
             call checkmpireturn(subName, mpierr)

             if (Debug) print *, subName,':: comp_rank: ',File%iosystem%comp_rank, &
                  ': received IOBUF size=',size(IOBUF)
          endif

          ! Read rank>0 first then go back and read 0
          ! so that we can re-use the rank 0 IOBUF

          if (File%iosystem%io_rank==0) then
             do i=1,File%iosystem%num_iotasks-1
                if (Debug) print *, subName,': 0: reading netcdf for ',i

                call MPI_RECV( temp_start, ndims, MPI_INTEGER, &
                     i,i,File%iosystem%IO_comm,status,mpierr)
                call CheckMPIReturn('read_nfdarray_int',mpierr)

                call MPI_RECV( temp_count, ndims, MPI_INTEGER, &
                     i,i,File%iosystem%IO_comm,status,mpierr)
                call CheckMPIReturn('read_nfdarray_int',mpierr)

                call MPI_RECV( iobuf_size, 1, MPI_INTEGER,    &
                     i,i,File%iosystem%IO_comm,status,mpierr)
                call CheckMPIReturn('read_nfdarray_int',mpierr)

                ierr=nf90_get_var( File%fh, varDesc%varid, &
                     IOBUF, temp_start(1:ndims), temp_count(1:ndims) )

                call MPI_SEND( IOBUF,iobuf_size, &
                     MPI_INTEGER, &
                     i,i,File%iosystem%IO_comm,mpierr)
                call CheckMPIReturn('read_nfdarray_int',mpierr)

                if (Debug) print *, subName,': 0: done reading netcdf for ',i
             end do ! i=1,File%iosystem%num_iotasks-1

             ! Read root data last

             if (Debug) print *, subName,': 0: reading netcdf for self', vardesc%varid, ndims, start, count

             temp_start(1:ndims)=start(1:ndims)
             temp_count(1:ndims)=count(1:ndims)

             ierr=nf90_get_var( File%fh, varDesc%varid, &
                  IOBUF, temp_start(1:ndims), temp_count(1:ndims) )

             if (Debug) print *, subName,': 0: done reading netcdf for self'

          endif ! File%iosystem%io_rank==0

#endif

       case default
          call bad_iotype(iotype,__PIO_FILE__,__LINE__)

       end select
    endif ! File%iosystem%IOproc
    call check_netcdf(File, ierr,__PIO_FILE__,__LINE__);
#ifdef TIMING
    call t_stopf("pio_read_nfdarray_int")
#endif

  end function read_nfdarray_int
end module pionfread_mod
