module nbi_out_avg

  !  module for scalar outputs data averaging; support scalar and 1d
  !  real*8 and integer arrays; 2d real*8 arrays also.
  use iso_c_binding, only: fp => c_double
  use ezcdf
  implicit none

  interface nbi_out_avg_sub
     module procedure &
          nbi_out_avg_sub_d0,nbi_out_avg_sub_d1,nbi_out_avg_sub_d2, &
          nbi_out_avg_sub_i0,nbi_out_avg_sub_i1,nbi_out_avg_sub_i2
  end interface
  
  private :: fp
  contains

    subroutine nbi_out_avg_sub_d0(icdf,zname,zd0,zwght,ierr)

      ! avg real*8 scalar

      integer, intent(in) :: icdf
      character*(*), intent(in) :: zname
      real(fp), intent(in) :: zd0
      real(fp), intent(in) :: zwght
      integer, intent(out) :: ierr

      real(fp) :: zd0_file

      call cdf_read(icdf,zname,zd0_file,ierr)
      if(ierr.ne.0) return

      zd0_file = (1-zwght)*zd0_file + zwght*zd0

      call cdf_write(icdf,zname,zd0_file)

    end subroutine nbi_out_avg_sub_d0

    subroutine nbi_out_avg_sub_d1(icdf,zname,zd1,zwght,ierr)

      ! avg real(fp) vector

      integer, intent(in) :: icdf
      character*(*), intent(in) :: zname
      real(fp), dimension(:), intent(in) :: zd1
      real(fp), intent(in) :: zwght
      integer, intent(out) :: ierr

      real(fp), dimension(:), allocatable :: zd1_file
      integer :: isize

      !------------------
      ierr = 0
      isize = size(zd1)
      if(isize.eq.0) return

      allocate(zd1_file(isize))

      call cdf_read(icdf,zname,zd1_file,ierr)
      if(ierr.ne.0) return

      zd1_file = (1-zwght)*zd1_file + zwght*zd1

      call cdf_write(icdf,zname,zd1_file)

      deallocate(zd1_file)

    end subroutine nbi_out_avg_sub_d1

    subroutine nbi_out_avg_sub_d2(icdf,zname,zd2,zwght,ierr)

      ! avg real(fp) 2d array

      integer, intent(in) :: icdf
      character*(*), intent(in) :: zname
      real(fp), dimension(:,:), intent(in) :: zd2
      real(fp), intent(in) :: zwght
      integer, intent(out) :: ierr

      real(fp), dimension(:,:), allocatable :: zd2_file
      integer :: isize1,isize2

      !------------------
      ierr = 0
      isize1 = size(zd2,1)
      isize2 = size(zd2,2)
      if(isize1.eq.0) return
      if(isize2.eq.0) return

      allocate(zd2_file(isize1,isize2))

      call cdf_read(icdf,zname,zd2_file,ierr)
      if(ierr.ne.0) return

      zd2_file = (1-zwght)*zd2_file + zwght*zd2

      call cdf_write(icdf,zname,zd2_file)

      deallocate(zd2_file)

    end subroutine nbi_out_avg_sub_d2

    subroutine nbi_out_avg_sub_i0(icdf,zname,ii0,zwght,ierr)

      ! avg integer scalar

      integer, intent(in) :: icdf
      character*(*), intent(in) :: zname
      integer, intent(in) :: ii0
      real(fp), intent(in) :: zwght
      integer, intent(out) :: ierr

      integer :: ii0_file
      real(fp) :: zwk

      call cdf_read(icdf,zname,ii0_file,ierr)
      if(ierr.ne.0) return

      zwk = (1-zwght)*ii0_file + zwght*ii0
      ii0_file = zwk

      call cdf_write(icdf,zname,ii0_file)

    end subroutine nbi_out_avg_sub_i0

    subroutine nbi_out_avg_sub_i1(icdf,zname,ii1,zwght,ierr)

      ! avg integer vector

      integer, intent(in) :: icdf
      character*(*), intent(in) :: zname
      integer, dimension(:), intent(in) :: ii1
      real(fp), intent(in) :: zwght
      integer, intent(out) :: ierr

      real(fp), dimension(:), allocatable :: zwk
      integer, dimension(:), allocatable :: ii1_file
      integer :: isize

      !------------------
      ierr = 0
      isize = size(ii1)
      if(isize.eq.0) return

      allocate(ii1_file(isize),zwk(isize))

      call cdf_read(icdf,zname,ii1_file,ierr)
      if(ierr.ne.0) return

      zwk = (1-zwght)*ii1_file + zwght*ii1
      ii1_file = zwk

      call cdf_write(icdf,zname,ii1_file)

      deallocate(ii1_file,zwk)

    end subroutine nbi_out_avg_sub_i1

    subroutine nbi_out_avg_sub_i2(icdf,zname,zi2,zwght,ierr)

      ! avg real(fp) 2d array

      integer, intent(in) :: icdf
      character*(*), intent(in) :: zname
      integer, dimension(:,:), intent(in) :: zi2
      real(fp), intent(in) :: zwght
      integer, intent(out) :: ierr

      integer, dimension(:,:), allocatable :: zi2_file
      integer :: isize1,isize2

      !------------------
      ierr = 0
      isize1 = size(zi2,1)
      isize2 = size(zi2,2)
      if(isize1.eq.0) return
      if(isize2.eq.0) return

      allocate(zi2_file(isize1,isize2))

      call cdf_read(icdf,zname,zi2_file,ierr)
      if(ierr.ne.0) return

      zi2_file = (1-zwght)*zi2_file + zwght*zi2

      call cdf_write(icdf,zname,zi2_file)

      deallocate(zi2_file)

    end subroutine nbi_out_avg_sub_i2

  
end module nbi_out_avg
