!= 遨榊�縺ｨ蟷ｳ蝮��謫堺ｽ�
!
!= Operation for integral and average
!
! Authors::   Yoshiyuki O. Takahashi, Yasuhiro MORIKAWA
! Version::   $Id: intavr_operate.F90,v 1.6 2014/05/07 09:39:23 murashin Exp $
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2008. All rights reserved.
! License::   See COPYRIGHT[link:../../../COPYRIGHT]
!

module intavr_operate
  !
  != 遨榊�縺ｨ蟷ｳ蝮��謫堺ｽ�
  !
  != Operation for integral and average
  !
  ! <b>Note that Japanese and English are described in parallel.</b>
  !
  ! 遨榊�縺ｧ逕ｨ縺�ｋ蠎ｧ讓咎㍾縺ｿ繧定��縺励◆遨榊�繧�ｹｳ蝮�桃菴懊�縺溘ａ縺ｮ髢｢謨ｰ繧呈署萓帙＠縺ｾ縺�.
  ! {SPMODEL 繝ｩ繧､繝悶Λ繝ｪ}[http://www.gfd-dennou.org/library/spmodel]
  ! 縺ｮ w_integral_module.f90 繧貞盾閠�↓菴懈�縺励∪縺励◆.
  !
  ! Functions for integral or average operation with weight for integration
  ! are provided
  ! This program is created referring to
  ! "w_integral_module.f90" in
  ! {SPMODEL library}[http://www.gfd-dennou.org/library/spmodel]
  !
  !== Procedures List
  !
  ! IntLonLat_xy           :: 邱ｯ蠎ｦ邨悟ｺｦ遨榊�
!!$  ! y_IntLon_xy, IntLon_x  :: 邨悟ｺｦ遨榊�
!!$  ! ya_IntLon_xya          :: 邨悟ｺｦ遨榊� (螟壼ｱ､逕ｨ)
!!$  ! x_IntLat_xy, IntLat_y  :: 邱ｯ蠎ｦ遨榊�
!!$  ! xa_IntLat_xya          :: 邱ｯ蠎ｦ遨榊� (螟壼ｱ､逕ｨ)
!!$  ! AvrLonLat_xy           :: 邱ｯ蠎ｦ邨悟ｺｦ蟷ｳ蝮�
!!$  ! y_AvrLon_xy, AvrLon_x  :: 邨悟ｺｦ蟷ｳ蝮�
!!$  ! ya_AvrLon_xya          :: 邨悟ｺｦ蟷ｳ蝮� (螟壼ｱ､逕ｨ)
!!$  ! x_AvrLat_xy, AvrLat_y  :: 邱ｯ蠎ｦ蟷ｳ蝮�
!!$  ! xa_AvrLat_xya          :: 邱ｯ蠎ｦ蟷ｳ蝮� (螟壼ｱ､逕ｨ)
  ! ---------------------  :: ---------------------
  ! y_IntLon_xy, IntLon_x  :: Meridional integral
!!$  ! ya_IntLon_xya          :: Meridional integral (for multi layer)
!!$  ! x_IntLat_xy, IntLat_y  :: Zonal integral
!!$  ! xa_IntLat_xya          :: Zonal integral (for multi layer)
!!$  ! AvrLonLat_xy           :: Zonal and meridional average
!!$  ! y_AvrLon_xy, AvrLon_x  :: Meridional average
!!$  ! ya_AvrLon_xya          :: Meridional average (for multi layer)
!!$  ! x_AvrLat_xy, AvrLat_y  :: Zonal average
!!$  ! xa_AvrLat_xya          :: Zonal average (for multi layer)
  !
  !--
  !== NAMELIST
  !
  ! NAMELIST#intavr_operate_nml
  !++

  ! 繝｢繧ｸ繝･繝ｼ繝ｫ蠑慕畑 ; USE statements
  !

  ! 蠎ｧ讓吶ョ繝ｼ繧ｿ險ｭ螳�
  ! Axes data settings
  !
  use axesset, only: &
    & x_Lon_Weight, &
                              ! $ \Delta \lambda $ [rad.] .
                              ! 邨悟ｺｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of longitude
    & y_Lat_Weight
                              ! $ \Delta \varphi $ [rad.] .
                              ! 邱ｯ蠎ｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of latitude

  ! 譬ｼ蟄千せ險ｭ螳�
  ! Grid points settings
  !
  use gridset, only: imax, & ! 邨悟ｺｦ譬ｼ蟄千せ謨ｰ.
                             ! Number of grid points in longitude
    &                jmax, & ! 邱ｯ蠎ｦ譬ｼ蟄千せ謨ｰ.
                             ! Number of grid points in latitude
    &                kmax    ! 驩帷峩螻､謨ｰ.
                             ! Number of vertical level

  ! 遞ｮ蛻･蝙九ヱ繝ｩ繝｡繧ｿ
  ! Kind type parameter
  !
  use dc_types, only: DP, &      ! 蛟咲ｲｾ蠎ｦ螳滓焚蝙�. Double precision.
    &                 STRING     ! 譁�ｭ怜�.       Strings.

  ! 繝｡繝�そ繝ｼ繧ｸ蜃ｺ蜉�
  ! Message output
  !
  use dc_message, only: MessageNotify

  ! 螳｣險譁� ; Declaration statements
  !
  implicit none
  private

  ! 蜈ｬ髢区焔邯壹″
  ! Public procedure
  !
  public:: IntLonLat_xy
  public:: a_IntLonLat_xya
!!$  public:: y_IntLon_xy, ya_IntLon_xya, IntLon_x
!!$  public:: x_IntLat_xy, xa_IntLat_xya, IntLat_y
!!$  public:: IntLat_y
!!$  public:: AvrLonLat_xy
!!$  public:: y_AvrLon_xy, ya_AvrLon_xya, AvrLon_x
!!$  public:: x_AvrLat_xy, xa_AvrLat_xya, AvrLat_y

  ! 蜈ｬ髢句､画焚
  ! Public variables
  !
  logical, save, public:: intavr_operate_inited = .false.
                              ! 蛻晄悄險ｭ螳壹ヵ繝ｩ繧ｰ.
                              ! Initialization flag

  ! 髱槫�髢句､画焚
  ! Private variables
  !

  character(*), parameter:: module_name = 'intavr_operate'
                              ! 繝｢繧ｸ繝･繝ｼ繝ｫ縺ｮ蜷咲ｧｰ.
                              ! Module name
  character(*), parameter:: version = &
    & '$Name:  $' // &
    & '$Id: intavr_operate.F90,v 1.6 2014/05/07 09:39:23 murashin Exp $'
                              ! 繝｢繧ｸ繝･繝ｼ繝ｫ縺ｮ繝舌�繧ｸ繝ｧ繝ｳ
                              ! Module version

  ! INTERFACE 譁� ; INTERFACE statements
  !

contains

  !-------------------------------------------------------------------

  function a_IntLonLat_xya( xya_Data )
    !
    ! 2 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ蜈ｨ鬆伜沺遨榊�(1 螻､逕ｨ).
    !
    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ x_Lon_Weight, y_Lat_Weight 繧呈寺縺代◆
    ! 邱丞柱繧定ｨ育ｮ励＠縺ｦ縺�ｋ.
    !
    ! Global integration of 2-dimensional (latitude and longitude)
    ! grid data.
    !
    ! Practically, the sum total of grid data is calculated
    ! by multiplying in each grid "x_Lon_Weight" and "y_Lat_Weight".
    !

    real(DP), intent(in) :: xya_Data       (:,:,:)
    real(DP)             :: a_IntLonLat_xya(size(xya_Data,3))

    ! 螳溯｡梧枚 ; Executable statement
    !

    a_IntLonLat_xya = a_IntLat_ya( ya_IntLon_xya( xya_Data ) )

  end function a_IntLonLat_xya

  !-------------------------------------------------------------------

  function IntLonLat_xy( xy_Data )
    !
    ! 2 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ蜈ｨ鬆伜沺遨榊�(1 螻､逕ｨ).
    !
    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ x_Lon_Weight, y_Lat_Weight 繧呈寺縺代◆
    ! 邱丞柱繧定ｨ育ｮ励＠縺ｦ縺�ｋ.
    !
    ! Global integration of 2-dimensional (latitude and longitude)
    ! grid data.
    !
    ! Practically, the sum total of grid data is calculated
    ! by multiplying in each grid "x_Lon_Weight" and "y_Lat_Weight".
    !

    real(DP), intent(in) :: xy_Data (0:imax-1, 1:jmax)
    real(DP)             :: IntLonLat_xy

    ! 螳溯｡梧枚 ; Executable statement
    !

    IntLonLat_xy = IntLat_y( y_IntLon_xy( xy_Data ) )

  end function IntLonLat_xy

  !-------------------------------------------------------------------

  function ya_IntLon_xya( xya_Data )
    !
    ! 2 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邨悟ｺｦ譁ｹ蜷醍ｩ榊�(1 螻､逕ｨ).
    !
    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ x_Lon_Weight 繧呈寺縺代◆
    ! 邱丞柱繧定ｨ育ｮ励＠縺ｦ縺�ｋ.
    !
    ! Zonal integration of 2-dimensional (latitude and longitude)
    ! grid data.
    !
    ! Practically, the sum total of grid data is calculated
    ! by multiplying in each grid "x_Lon_Weight".
    !

    real(DP), intent(in) :: xya_Data     (:,:,:)
    real(DP)             :: ya_IntLon_xya(size(xya_Data,2), size(xya_Data,3))

    ! 菴懈･ｭ螟画焚
    ! Work variables
    !
    integer:: lmax
    integer:: i               ! 邨悟ｺｦ譁ｹ蜷代↓蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
                              ! Work variables for DO loop in longitudinal direction
    integer:: j               ! 邱ｯ蠎ｦ譁ｹ蜷代↓蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
                              ! Work variables for DO loop in latitudinal direction
    integer:: l

    ! 螳溯｡梧枚 ; Executable statement
    !
    lmax = size( xya_Data, 3 )

    ya_IntLon_xya = 0.0_DP
    do l = 1, lmax
      do j = 1, jmax
        do i = 0, imax - 1
!!$          ya_IntLon_xya(j,l) = ya_IntLon_xya(j,l) + xya_Data(i,j,l) * x_Lon_Weight(i)
          ya_IntLon_xya(j,l) = ya_IntLon_xya(j,l) + xya_Data(i+1,j,l) * x_Lon_Weight(i)
        end do
      end do
    end do

  end function ya_IntLon_xya

  !-------------------------------------------------------------------

  function y_IntLon_xy( xy_Data )
    !
    ! 2 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邨悟ｺｦ譁ｹ蜷醍ｩ榊�(1 螻､逕ｨ).
    !
    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ x_Lon_Weight 繧呈寺縺代◆
    ! 邱丞柱繧定ｨ育ｮ励＠縺ｦ縺�ｋ.
    !
    ! Zonal integration of 2-dimensional (latitude and longitude)
    ! grid data.
    !
    ! Practically, the sum total of grid data is calculated
    ! by multiplying in each grid "x_Lon_Weight".
    !

    real(DP), intent(in) :: xy_Data (0:imax-1, 1:jmax)
    real(DP)             :: y_IntLon_xy (1:jmax)

    ! 菴懈･ｭ螟画焚
    ! Work variables
    !
    integer:: i               ! 邨悟ｺｦ譁ｹ蜷代↓蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
                              ! Work variables for DO loop in longitudinal direction
    integer:: j               ! 邱ｯ蠎ｦ譁ｹ蜷代↓蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
                              ! Work variables for DO loop in latitudinal direction

    ! 螳溯｡梧枚 ; Executable statement
    !

    y_IntLon_xy = 0.0_DP
    do j = 1, jmax
      do i = 0, imax - 1
        y_IntLon_xy(j) = y_IntLon_xy(j) + xy_Data (i,j) * x_Lon_Weight(i)
      end do
    end do

  end function y_IntLon_xy

#ifdef LIB_MPI
  !-------------------------------------------------------------------

  function a_IntLat_ya( ya_Data )
    !
    ! 1 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ蜈ｨ鬆伜沺蟷ｳ蝮�(1 螻､逕ｨ).
    !
    ! Global mean of 2-dimensional (latitude and longitude)
    ! grid data.
    !

    ! MPI
    !
    use mpi_wrapper, only: nprocs, myrank, &
      & MPIWrapperISend, &
      & MPIWrapperIRecv, &
      & MPIWrapperWait

    ! 譬ｼ蟄千せ謨ｰ繝ｻ譛螟ｧ豕｢謨ｰ險ｭ螳�
    ! Number of grid points and maximum truncated wavenumber settings
    !
    use gridset, only: a_jmax, jmax_max

    real(DP), intent(in) :: ya_Data (:,:)
    real(DP)             :: a_IntLat_ya(size(ya_Data,2))

    ! Local variable
    !
    integer               :: lmax
    real(DP), allocatable :: aa_SendBuf (:,:)
    real(DP), allocatable :: aaa_RecvBuf(:,:,:)
    integer , allocatable :: a_iReqSend (:)
    integer , allocatable :: a_iReqRecv (:)

    integer               :: j
    integer               :: l
    integer               :: n

    ! 螳溯｡梧枚 ; Executable statement
    !
    lmax = size(ya_Data,2)

    allocate( aa_SendBuf (1:jmax_max, 1:lmax) )
    allocate( aaa_RecvBuf(1:jmax_max, 1:lmax, 0:nprocs-1) )
    allocate( a_iReqSend(0:nprocs-1) )
    allocate( a_iReqRecv(0:nprocs-1) )

    do l = 1, lmax
      do j = 1, jmax
        aa_SendBuf(j,l) = ya_Data(j,l) * y_Lat_Weight(j)
      end do
      do j = jmax+1, jmax_max
        aa_SendBuf(j,l) = -1.0_DP
      end do
    end do

    do n = 0, nprocs-1
      if ( n == myrank ) then
        aaa_RecvBuf(:,:,n) = aa_SendBuf
      else
        call MPIWrapperISend( n, jmax_max, lmax, aa_SendBuf        , a_iReqSend(n) )
        call MPIWrapperIRecv( n, jmax_max, lmax, aaa_RecvBuf(:,:,n), a_iReqRecv(n) )
      end if
    end do
    do n = 0, nprocs-1
      if ( n == myrank ) cycle
      call MPIWrapperWait( a_iReqSend(n) )
      call MPIWrapperWait( a_iReqRecv(n) )
    end do

    a_IntLat_ya = 0.0_DP
    do n = nprocs-1, 0, -1
      do l = 1, lmax
        do j = 1, a_jmax(n) / 2
          a_IntLat_ya(l) = a_IntLat_ya(l) + aaa_RecvBuf(j,l,n)
        end do
      end do
    end do
    do n = 0, nprocs-1
      do l = 1, lmax
        do j = a_jmax(n) / 2 + 1, a_jmax(n)
          a_IntLat_ya(l) = a_IntLat_ya(l) + aaa_RecvBuf(j,l,n)
        end do
      end do
    end do

    deallocate( aa_SendBuf  )
    deallocate( aaa_RecvBuf )
    deallocate( a_iReqSend  )
    deallocate( a_iReqRecv  )

  end function a_IntLat_ya

  !-------------------------------------------------------------------

  function IntLat_y( y_Data )
    !
    ! 1 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ蜈ｨ鬆伜沺蟷ｳ蝮�(1 螻､逕ｨ).
    !
    ! Global mean of 2-dimensional (latitude and longitude)
    ! grid data.
    !

    ! MPI
    !
    use mpi_wrapper, only: nprocs, myrank, &
      & MPIWrapperISend, &
      & MPIWrapperIRecv, &
      & MPIWrapperWait

    ! 譬ｼ蟄千せ謨ｰ繝ｻ譛螟ｧ豕｢謨ｰ險ｭ螳�
    ! Number of grid points and maximum truncated wavenumber settings
    !
    use gridset, only: a_jmax, jmax_max

    real(DP), intent(in) :: y_Data (1:jmax)
    real(DP)             :: IntLat_y

    ! Local variable
    !
    real(DP), allocatable :: a_SendBuf (:)
    real(DP), allocatable :: aa_RecvBuf(:,:)
    integer , allocatable :: a_iReqSend(:)
    integer , allocatable :: a_iReqRecv(:)

    integer               :: j
    integer               :: n

    ! 螳溯｡梧枚 ; Executable statement
    !

    allocate( a_SendBuf (1:jmax_max) )
    allocate( aa_RecvBuf(1:jmax_max,0:nprocs-1) )
    allocate( a_iReqSend(0:nprocs-1) )
    allocate( a_iReqRecv(0:nprocs-1) )

    do j = 1, jmax
      a_SendBuf(j) = y_Data(j) * y_Lat_Weight(j)
    end do
    do j = jmax+1, jmax_max
      a_SendBuf(j) = -1.0_DP
    end do

    do n = 0, nprocs-1
      if ( n == myrank ) then
        aa_RecvBuf(:,n) = a_SendBuf
      else
        call MPIWrapperISend( n, jmax_max, a_SendBuf      , a_iReqSend(n) )
        call MPIWrapperIRecv( n, jmax_max, aa_RecvBuf(:,n), a_iReqRecv(n) )
      end if
    end do
    do n = 0, nprocs-1
      if ( n == myrank ) cycle
      call MPIWrapperWait( a_iReqSend(n) )
      call MPIWrapperWait( a_iReqRecv(n) )
    end do

    IntLat_y = 0.0d0
    do n = nprocs-1, 0, -1
      do j = 1, a_jmax(n) / 2
        IntLat_y = IntLat_y + aa_RecvBuf(j,n)
      end do
    end do
    do n = 0, nprocs-1
      do j = a_jmax(n) / 2 + 1, a_jmax(n)
        IntLat_y = IntLat_y + aa_RecvBuf(j,n)
      end do
    end do

    deallocate( a_SendBuf  )
    deallocate( aa_RecvBuf )
    deallocate( a_iReqSend )
    deallocate( a_iReqRecv )

  end function IntLat_y

#else
  !-------------------------------------------------------------------

  function a_IntLat_ya( ya_Data )
    !
    ! 1 谺｡蜈�ｷｯ蠎ｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邱ｯ蠎ｦ譁ｹ蜷醍ｩ榊�(1 螻､逕ｨ).
    !
    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ y_Lat_Weight 繧呈寺縺代◆
    ! 邱丞柱繧定ｨ育ｮ励＠縺ｦ縺�ｋ.
    !
    ! Meridonal integration of 1-dimensional (latitude)
    ! grid data.
    !
    ! Practically, the sum total of grid data is calculated
    ! by multiplying in each grid "y_Lat_Weight".
    !
    real(DP), intent(in) :: ya_Data    (:,:)
    real(DP)             :: a_IntLat_ya(size(ya_Data,2))

    ! 菴懈･ｭ螟画焚
    ! Work variables
    !
    integer :: lmax
    integer :: l

    ! 螳溯｡梧枚 ; Executable statement
    !
    lmax = size(ya_Data,2)

    do l = 1, lmax
      a_IntLat_ya(l) = sum( ya_Data(:,l) * y_Lat_Weight )
    end do

  end function a_IntLat_ya

  !-------------------------------------------------------------------

  function IntLat_y( y_Data )
    !
    ! 1 谺｡蜈�ｷｯ蠎ｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邱ｯ蠎ｦ譁ｹ蜷醍ｩ榊�(1 螻､逕ｨ).
    !
    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ y_Lat_Weight 繧呈寺縺代◆
    ! 邱丞柱繧定ｨ育ｮ励＠縺ｦ縺�ｋ.
    !
    ! Meridonal integration of 1-dimensional (latitude)
    ! grid data.
    !
    ! Practically, the sum total of grid data is calculated
    ! by multiplying in each grid "y_Lat_Weight".
    !
    real(DP), intent(in) :: y_Data (1:jmax)
    real(DP)             :: IntLat_y

    ! 菴懈･ｭ螟画焚
    ! Work variables
    !

    ! 螳溯｡梧枚 ; Executable statement
    !
    IntLat_y = sum( y_Data * y_Lat_Weight )

  end function IntLat_y

#endif
  !-------------------------------------------------------------------
!!$
!!$  function AvrLonLat_xy( xy_Data )
!!$    !
!!$    ! 2 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ蜈ｨ鬆伜沺蟷ｳ蝮�(1 螻､逕ｨ).
!!$    !
!!$    ! Global mean of 2-dimensional (latitude and longitude)
!!$    ! grid data.
!!$    !
!!$
!!$    real(DP), intent(in):: xy_Data (0:imax-1, 1:jmax)
!!$
!!$
!!$    ! Local variable
!!$    !
!!$    real(DP)              :: AvrLonLat_xy
!!$
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$
!!$    ! Old one to be deleted
!!$!    AvrLonLat_xy = AvrLon_x( x_AvrLat_xy( xy_Data ) )
!!$
!!$    AvrLonLat_xy = AvrLat_y( y_AvrLon_xy( xy_Data ) )
!!$
!!$
!!$  end function AvrLonLat_xy
!!$
!!$  !-------------------------------------------------------------------
!!$
!!$  function x_IntLat_xy( xy_Data )
!!$    !
!!$    ! 2 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邱ｯ蠎ｦ譁ｹ蜷醍ｩ榊�(1 螻､逕ｨ).
!!$    !
!!$    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ y_Lat_Weight 繧呈寺縺代◆
!!$    ! 邱丞柱繧定ｨ育ｮ励＠縺ｦ縺�ｋ.
!!$    !
!!$    ! Meridional integration of 2-dimensional (latitude and longitude)
!!$    ! grid data.
!!$    !
!!$    ! Practically, the sum total of grid data is calculated
!!$    ! by multiplying in each grid "y_Lat_Weight".
!!$    !
!!$    real(DP), intent(in):: xy_Data (0:imax-1, 1:jmax)
!!$    real(DP):: x_IntLat_xy (0:imax-1)
!!$
!!$    ! 菴懈･ｭ螟画焚
!!$    ! Work variables
!!$    !
!!$    integer:: j               ! 邱ｯ蠎ｦ譁ｹ蜷代↓蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
!!$                              ! Work variables for DO loop in latitude
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$    x_IntLat_xy = 0.0_DP
!!$    do j = 1, jmax
!!$      x_IntLat_xy = x_IntLat_xy + xy_Data (:,j) * y_Lat_Weight(j)
!!$    enddo
!!$  end function x_IntLat_xy
!!$
!!$  !-------------------------------------------------------------------
!!$
!!$  function xa_IntLat_xya( xya_Data )
!!$    !
!!$    ! 3 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邱ｯ蠎ｦ譁ｹ蜷醍ｩ榊�(螟壼ｱ､逕ｨ).
!!$    !
!!$    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ y_Lat_Weight 繧呈寺縺代◆
!!$    ! 邱丞柱繧定ｨ育ｮ励＠縺ｦ縺�ｋ.
!!$    !
!!$    ! Meridional integration of 3-dimensional (latitude and longitude)
!!$    ! grid data. (for multi layer)
!!$    !
!!$    ! Practically, the sum total of grid data is calculated
!!$    ! by multiplying in each grid "y_Lat_Weight".
!!$    !
!!$    real(DP), intent(in):: xya_Data (0:imax-1, 1:jmax, 1:kmax)
!!$    real(DP):: xa_IntLat_xya (0:imax-1, 1:kmax)
!!$
!!$    ! 菴懈･ｭ螟画焚
!!$    ! Work variables
!!$    !
!!$    integer:: k               ! 驩帷峩譁ｹ蜷代↓蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
!!$                              ! Work variables for DO loop in vertical direction
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$    do k = 1, kmax
!!$      xa_IntLat_xya(:,k) = x_IntLat_xy( xya_Data(:,:,k) )
!!$    end do
!!$  end function xa_IntLat_xya
!!$
!!$  !-------------------------------------------------------------------
!!$
!!$  function ya_IntLon_xya( xya_Data )
!!$    !
!!$    ! 3 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邨悟ｺｦ譁ｹ蜷醍ｩ榊�(螟壼ｱ､逕ｨ).
!!$    !
!!$    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ x_Lon_Weight 繧呈寺縺代◆
!!$    ! 邱丞柱繧定ｨ育ｮ励＠縺ｦ縺�ｋ.
!!$    !
!!$    ! Zonal integration of 3-dimensional (latitude and longitude)
!!$    ! grid data. (for multi layer)
!!$    !
!!$    ! Practically, the sum total of grid data is calculated
!!$    ! by multiplying in each grid "x_Lon_Weight".
!!$    !
!!$    real(DP), intent(in):: xya_Data (0:imax-1, 1:jmax, 1:kmax)
!!$    real(DP):: ya_IntLon_xya (1:jmax,1:kmax)
!!$
!!$    ! 菴懈･ｭ螟画焚
!!$    ! Work variables
!!$    !
!!$    integer:: k               ! 驩帷峩譁ｹ蜷代↓蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
!!$                              ! Work variables for DO loop in vertical direction
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$    do k = 1, kmax
!!$      ya_IntLon_xya(:,k) = y_IntLon_xy( xya_Data(:,:,k) )
!!$    end do
!!$  end function ya_IntLon_xya
!!$
!!$  !-------------------------------------------------------------------
!!$
!!$  function IntLon_x( x_Data )
!!$    !
!!$    ! 1 谺｡蜈�ｵ悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邨悟ｺｦ譁ｹ蜷醍ｩ榊�(1 螻､逕ｨ).
!!$    !
!!$    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ x_Lon_Weight 繧呈寺縺代◆
!!$    ! 邱丞柱繧定ｨ育ｮ励＠縺ｦ縺�ｋ.
!!$    !
!!$    ! Zonal integration of 1-dimensional (longitude)
!!$    ! grid data.
!!$    !
!!$    ! Practically, the sum total of grid data is calculated
!!$    ! by multiplying in each grid "x_Lon_Weight".
!!$    !
!!$    real(DP), intent(in):: x_Data (0:imax-1)
!!$    real(DP):: IntLon_x
!!$
!!$    ! 菴懈･ｭ螟画焚
!!$    ! Work variables
!!$    !
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$    IntLon_x = sum( x_Data * x_Lon_Weight )
!!$  end function IntLon_x
!!$
!!$  !-------------------------------------------------------------------
!!$
!!$  function x_AvrLat_xy( xy_Data )
!!$    !
!!$    ! 2 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邱ｯ蠎ｦ譁ｹ蜷大ｹｳ蝮�(1 螻､逕ｨ).
!!$    !
!!$    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ y_Lat_Weight 繧呈寺縺代◆
!!$    ! 邱丞柱繧定ｨ育ｮ励＠, y_Lat_Weight 縺ｮ邱丞柱縺ｧ蜑ｲ繧九％縺ｨ縺ｧ
!!$    ! 蟷ｳ蝮�＠縺ｦ縺�ｋ.
!!$    !
!!$    ! Meridional mean of 2-dimensional (latitude and longitude)
!!$    ! grid data.
!!$    !
!!$    ! Practically, the mean grid data is calculated
!!$    ! by multiplying in each grid "y_Lat_Weight"
!!$    ! and deviding by the sum total of "y_Lat_Weight".
!!$    !
!!$    real(DP), intent(in):: xy_Data (0:imax-1, 1:jmax)
!!$    real(DP):: x_AvrLat_xy (0:imax-1)
!!$
!!$    ! 菴懈･ｭ螟画焚
!!$    ! Work variables
!!$    !
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$    x_AvrLat_xy = x_IntLat_xy ( xy_Data ) / sum( y_Lat_Weight )
!!$  end function x_AvrLat_xy
!!$
!!$  !-------------------------------------------------------------------
!!$
!!$  function xa_AvrLat_xya( xya_Data )
!!$    !
!!$    ! 3 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邱ｯ蠎ｦ譁ｹ蜷大ｹｳ蝮�(螟壼ｱ､逕ｨ).
!!$    !
!!$    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ y_Lat_Weight 繧呈寺縺代◆
!!$    ! 邱丞柱繧定ｨ育ｮ励＠, y_Lat_Weight 縺ｮ邱丞柱縺ｧ蜑ｲ繧九％縺ｨ縺ｧ
!!$    ! 蟷ｳ蝮�＠縺ｦ縺�ｋ.
!!$    !
!!$    ! Meridional mean of 3-dimensional (latitude and longitude)
!!$    ! grid data. (for multi layer)
!!$    !
!!$    ! Practically, the mean grid data is calculated
!!$    ! by multiplying in each grid "y_Lat_Weight"
!!$    ! and deviding by the sum total of "y_Lat_Weight".
!!$    !
!!$    real(DP), intent(in):: xya_Data (0:imax-1, 1:jmax, 1:kmax)
!!$    real(DP):: xa_AvrLat_xya (0:imax-1, 1:kmax)
!!$
!!$    ! 菴懈･ｭ螟画焚
!!$    ! Work variables
!!$    !
!!$    integer:: k               ! 驩帷峩譁ｹ蜷代↓蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
!!$                              ! Work variables for DO loop in vertical direction
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$    do k = 1, kmax
!!$      xa_AvrLat_xya(:,k) = x_AvrLat_xy( xya_Data(:,:,k) )
!!$    end do
!!$  end function xa_AvrLat_xya
!!$
!!$  !-------------------------------------------------------------------
!!$
!!$  function y_AvrLon_xy( xy_Data )
!!$    !
!!$    ! 2 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邨悟ｺｦ譁ｹ蜷大ｹｳ蝮�(1 螻､逕ｨ).
!!$    !
!!$    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ x_Lon_Weight 繧呈寺縺代◆
!!$    ! 邱丞柱繧定ｨ育ｮ励＠, x_Lon_Weight 縺ｮ邱丞柱縺ｧ蜑ｲ繧九％縺ｨ縺ｧ
!!$    ! 蟷ｳ蝮�＠縺ｦ縺�ｋ.
!!$    !
!!$    ! Zonal mean of 2-dimensional (latitude and longitude)
!!$    ! grid data.
!!$    !
!!$    ! Practically, the mean grid data is calculated
!!$    ! by multiplying in each grid "x_Lon_Weight"
!!$    ! and deviding by the sum total of "x_Lon_Weight".
!!$    !
!!$    real(DP), intent(in):: xy_Data (0:imax-1, 1:jmax)
!!$    real(DP):: y_AvrLon_xy (1:jmax)
!!$
!!$    ! 菴懈･ｭ螟画焚
!!$    ! Work variables
!!$    !
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$    y_AvrLon_xy = y_IntLon_xy( xy_Data ) / sum( x_Lon_Weight )
!!$  end function y_AvrLon_xy
!!$
!!$  !-------------------------------------------------------------------
!!$
!!$  function ya_AvrLon_xya( xya_Data )
!!$    !
!!$    ! 3 谺｡蜈�ｷｯ蠎ｦ邨悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邨悟ｺｦ譁ｹ蜷大ｹｳ蝮�(螟壼ｱ､逕ｨ).
!!$    !
!!$    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ x_Lon_Weight 繧呈寺縺代◆
!!$    ! 邱丞柱繧定ｨ育ｮ励＠, x_Lon_Weight 縺ｮ邱丞柱縺ｧ蜑ｲ繧九％縺ｨ縺ｧ
!!$    ! 蟷ｳ蝮�＠縺ｦ縺�ｋ.
!!$    !
!!$    ! Zonal mean of 3-dimensional (latitude and longitude)
!!$    ! grid data. (for multi layer)
!!$    !
!!$    ! Practically, the mean grid data is calculated
!!$    ! by multiplying in each grid "x_Lon_Weight"
!!$    ! and deviding by the sum total of "x_Lon_Weight".
!!$    !
!!$    real(DP), intent(in):: xya_Data (0:imax-1, 1:jmax, 1:kmax)
!!$    real(DP):: ya_AvrLon_xya (1:jmax, 1:kmax)
!!$
!!$    ! 菴懈･ｭ螟画焚
!!$    ! Work variables
!!$    !
!!$    integer:: k               ! 驩帷峩譁ｹ蜷代↓蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
!!$                              ! Work variables for DO loop in vertical direction
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$    do k = 1, kmax
!!$      ya_AvrLon_xya(:,k) = y_AvrLon_xy( xya_Data(:,:,k) )
!!$    end do
!!$  end function ya_AvrLon_xya
!!$
!!$#ifdef LIB_MPI
!!$  !-------------------------------------------------------------------
!!$
!!$  function AvrLat_y( y_Data )
!!$    !
!!$    ! 1 谺｡蜈�ｷｯ蠎ｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邱ｯ蠎ｦ譁ｹ蜷大ｹｳ蝮�(1 螻､逕ｨ).
!!$    !
!!$    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ y_Lat_Weight 繧呈寺縺代◆
!!$    ! 邱丞柱繧定ｨ育ｮ励＠, y_Lat_Weight 縺ｮ邱丞柱縺ｧ蜑ｲ繧九％縺ｨ縺ｧ
!!$    ! 蟷ｳ蝮�＠縺ｦ縺�ｋ.
!!$    !
!!$    ! Meridonal mean of 1-dimensional (latitude)
!!$    ! grid data.
!!$    !
!!$    ! Practically, the sum total of grid data is calculated
!!$    ! by multiplying in each grid "y_Lat_Weight"
!!$    ! and deviding by the sum total of "y_Lat_Weight".
!!$    !
!!$
!!$    ! MPI
!!$    !
!!$    use mpi_wrapper, only: nprocs, myrank, &
!!$      & MPIWrapperISend, &
!!$      & MPIWrapperIRecv, &
!!$      & MPIWrapperWait
!!$
!!$    ! 譬ｼ蟄千せ謨ｰ繝ｻ譛螟ｧ豕｢謨ｰ險ｭ螳�
!!$    ! Number of grid points and maximum truncated wavenumber settings
!!$    !
!!$    use gridset, only: a_jmax, jmax_max
!!$
!!$    real(DP), intent(in):: y_Data (1:jmax)
!!$    real(DP):: AvrLat_y
!!$
!!$    ! 菴懈･ｭ螟画焚
!!$    ! Work variables
!!$    !
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$
!!$    real(DP), allocatable :: a_SendBuf (:)
!!$    real(DP), allocatable :: aa_RecvBuf(:,:)
!!$    integer , allocatable :: a_iReqSend(:)
!!$    integer , allocatable :: a_iReqRecv(:)
!!$
!!$    real(DP)              :: SumWeight
!!$
!!$    integer               :: j
!!$    integer               :: n
!!$
!!$    allocate( a_SendBuf (1:jmax_max) )
!!$    allocate( aa_RecvBuf(1:jmax_max,0:nprocs-1) )
!!$    allocate( a_iReqSend(0:nprocs-1) )
!!$    allocate( a_iReqRecv(0:nprocs-1) )
!!$
!!$    do j = 1, jmax
!!$      a_SendBuf(j) = y_Lat_Weight(j)
!!$    end do
!!$    do j = jmax+1, jmax_max
!!$      a_SendBuf(j) = -1.0d0
!!$    end do
!!$
!!$    do n = 0, nprocs-1
!!$      if ( n == myrank ) then
!!$        do j = 1, jmax
!!$          aa_RecvBuf(:,n) = a_SendBuf
!!$        end do
!!$      else
!!$        call MPIWrapperISend( n, jmax_max, a_SendBuf      , a_iReqSend(n) )
!!$        call MPIWrapperIRecv( n, jmax_max, aa_RecvBuf(:,n), a_iReqRecv(n) )
!!$      end if
!!$    end do
!!$    do n = 0, nprocs-1
!!$      if ( n == myrank ) cycle
!!$      call MPIWrapperWait( a_iReqSend(n) )
!!$      call MPIWrapperWait( a_iReqRecv(n) )
!!$    end do
!!$
!!$
!!$    if ( nprocs == 1 ) then
!!$      SumWeight = 0.0d0
!!$      do n = 0, nprocs-1
!!$        do j = 1, a_jmax(n)
!!$          SumWeight = SumWeight + aa_RecvBuf(j,n)
!!$        end do
!!$      end do
!!$    else
!!$
!!$      write( 6, * ) 'THIS WOULD BE WRONG.'
!!$
!!$      SumWeight = 0.0d0
!!$      do n = nprocs-1, 0, -1
!!$        do j = a_jmax(n), a_jmax(n) / 2 + 1, -1
!!$          SumWeight = SumWeight + aa_RecvBuf(j,n)
!!$        end do
!!$      end do
!!$      do n = 0, nprocs-1
!!$        do j = 1, a_jmax(n) / 2
!!$          SumWeight = SumWeight + aa_RecvBuf(j,n)
!!$        end do
!!$      end do
!!$    end if
!!$
!!$    deallocate( a_SendBuf  )
!!$    deallocate( aa_RecvBuf )
!!$    deallocate( a_iReqSend )
!!$    deallocate( a_iReqRecv )
!!$
!!$
!!$    AvrLat_y = IntLat_y( y_Data ) / SumWeight
!!$
!!$  end function AvrLat_y
!!$
!!$#else
!!$  !-------------------------------------------------------------------
!!$
!!$  function AvrLat_y( y_Data )
!!$    !
!!$    ! 1 谺｡蜈�ｷｯ蠎ｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邱ｯ蠎ｦ譁ｹ蜷大ｹｳ蝮�(1 螻､逕ｨ).
!!$    !
!!$    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ y_Lat_Weight 繧呈寺縺代◆
!!$    ! 邱丞柱繧定ｨ育ｮ励＠, y_Lat_Weight 縺ｮ邱丞柱縺ｧ蜑ｲ繧九％縺ｨ縺ｧ
!!$    ! 蟷ｳ蝮�＠縺ｦ縺�ｋ.
!!$    !
!!$    ! Meridonal mean of 1-dimensional (latitude)
!!$    ! grid data.
!!$    !
!!$    ! Practically, the sum total of grid data is calculated
!!$    ! by multiplying in each grid "y_Lat_Weight"
!!$    ! and deviding by the sum total of "y_Lat_Weight".
!!$    !
!!$    real(DP), intent(in):: y_Data (1:jmax)
!!$    real(DP):: AvrLat_y
!!$
!!$    ! 菴懈･ｭ螟画焚
!!$    ! Work variables
!!$    !
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$
!!$    AvrLat_y = IntLat_y( y_Data ) / sum( y_Lat_Weight )
!!$
!!$  end function AvrLat_y
!!$
!!$#endif
!!$  !-------------------------------------------------------------------
!!$
!!$  function AvrLon_x( x_Data )
!!$    !
!!$    ! 1 谺｡蜈�ｵ悟ｺｦ譬ｼ蟄千せ繝��繧ｿ縺ｮ邨悟ｺｦ譁ｹ蜷大ｹｳ蝮�(1 螻､逕ｨ).
!!$    !
!!$    ! 螳滄圀縺ｫ縺ｯ譬ｼ蟄千せ繝��繧ｿ蜷�せ豈弱↓ x_Lon_Weight 繧呈寺縺代◆
!!$    ! 邱丞柱繧定ｨ育ｮ励＠, x_Lon_Weight 縺ｮ邱丞柱縺ｧ蜑ｲ繧九％縺ｨ縺ｧ
!!$    ! 蟷ｳ蝮�＠縺ｦ縺�ｋ.
!!$    !
!!$    ! Zonal mean of 1-dimensional (longitude)
!!$    ! grid data.
!!$    !
!!$    ! Practically, the sum total of grid data is calculated
!!$    ! by multiplying in each grid "x_Lon_Weight"
!!$    ! and deviding by the sum total of "x_Lon_Weight".
!!$    !
!!$    real(DP), intent(in):: x_Data (0:imax-1)
!!$    real(DP):: AvrLon_x
!!$
!!$    ! 菴懈･ｭ螟画焚
!!$    ! Work variables
!!$    !
!!$
!!$    ! 螳溯｡梧枚 ; Executable statement
!!$    !
!!$    AvrLon_x = IntLon_x( x_Data ) / sum( x_Lon_Weight )
!!$  end function AvrLon_x
!!$

  !--------------------------------------------------------------------------------------

  subroutine IntAvrOprInit
    !
    ! intavr_operate 繝｢繧ｸ繝･繝ｼ繝ｫ縺ｮ蛻晄悄蛹悶ｒ陦後＞縺ｾ縺�.
    ! NAMELIST#intavr_operate_nml 縺ｮ隱ｭ縺ｿ霎ｼ縺ｿ縺ｯ縺薙�謇狗ｶ壹″縺ｧ陦後ｏ繧後∪縺�.
    !
    ! "intavr_operate" module is initialized.
    ! "NAMELIST#intavr_operate_nml" is loaded in this procedure.
    !

    ! 繝｢繧ｸ繝･繝ｼ繝ｫ蠑慕畑 ; USE statements
    !

    ! 螳｣險譁� ; Declaration statements
    !

!!$    integer:: unit_nml        ! NAMELIST 繝輔ぃ繧､繝ｫ繧ｪ繝ｼ繝励Φ逕ｨ陬�ｽｮ逡ｪ蜿ｷ.
!!$                              ! Unit number for NAMELIST file open
!!$    integer:: iostat_nml      ! NAMELIST 隱ｭ縺ｿ霎ｼ縺ｿ譎ゅ� IOSTAT.
!!$                              ! IOSTAT of NAMELIST read

    ! NAMELIST 螟画焚鄒､
    ! NAMELIST group name
    !
!!$    namelist /intavr_operate_nml/
          !
          ! 繝�ヵ繧ｩ繝ｫ繝亥､縺ｫ縺､縺�※縺ｯ蛻晄悄蛹匁焔邯� "intavr_operate#IntAvrOprInit"
          ! 縺ｮ繧ｽ繝ｼ繧ｹ繧ｳ繝ｼ繝峨ｒ蜿ら�縺ｮ縺薙→.
          !
          ! Refer to source codes in the initialization procedure
          ! "intavr_operate#IntAvrOprInit" for the default values.
          !

    ! 螳溯｡梧枚 ; Executable statement
    !

    if ( intavr_operate_inited ) return

    ! 繝�ヵ繧ｩ繝ｫ繝亥､縺ｮ險ｭ螳�
    ! Default values settings
    !

!!$    ! NAMELIST 縺ｮ隱ｭ縺ｿ霎ｼ縺ｿ
!!$    ! NAMELIST is input
!!$    !
!!$    if ( trim(namelist_filename) /= '' ) then
!!$      call FileOpen( unit_nml, &          ! (out)
!!$        & namelist_filename, mode = 'r' ) ! (in)
!!$
!!$      rewind( unit_nml )
!!$      read( unit_nml, &           ! (in)
!!$        & nml = intavr_operate_nml, &  ! (out)
!!$        & iostat = iostat_nml )   ! (out)
!!$      close( unit_nml )
!!$
!!$      call NmlutilMsg( iostat_nml, module_name ) ! (in)
!!$    end if

    ! 蜊ｰ蟄� ; Print
    !
    call MessageNotify( 'M', module_name, '----- Initialization Messages -----' )
    call MessageNotify( 'M', module_name, '-- version = %c', c1 = trim(version) )
    intavr_operate_inited = .true.
  end subroutine IntAvrOprInit

  !--------------------------------------------------------------------------------------

end module intavr_operate