! -*- mode: f90; coding: utf-8 -*-
!-------------------------------------------------------------------------
! Copyright (c) 2025 SPMODEL Development Group. All rights reserved.
!
! 履歴  2025/12/15  竹広真一
!-------------------------------------------------------------------------
!> @author Shin-ichi Takehiro, Youhei SASAKI
!> @copyright Copyright (C) SPMODEL Development Group, 2025.
!>            License is MIT/X11. see [COPYRIGHT](@ref COPYRIGHT) in detail
!> @brief
!> @ref w_zonal_module の下部モジュール: 積分・平均
!>
!> @warning
!> 本モジュールを直接呼ぶ事は想定されていないことに注意されたい．
!> ユーザは @ref w_zonal_module を呼ぶこと．
!>
module w_zonal_module_integral
  use dc_types, only: DP
  use w_zonal_module_base, only : im, jm, x_Lon_Weight, y_Lat_Weight
  implicit none
  private
  public IntLonLat_xy
  public y_IntLon_xy
  public IntLon_x
  public x_IntLat_xy
  public IntLat_y
  public AvrLonLat_xy
  public y_AvrLon_xy
  public AvrLon_x
  public x_AvrLat_xy
  public AvrLat_y

contains

  !---------------------------------------------------------------------
  !> 1 次元緯度(Y)格子点データの Y 方向積分(1 層用).
  function IntLat_y(y_data)
    !> 1 次元緯度(Y)格子点データ
    real(DP), intent(in) :: y_data(1:jm)
    !> 積分値
    real(DP)             :: IntLat_y

    IntLat_y = sum(y_data * y_Lat_weight)

  end function IntLat_y

  !---------------------------------------------------------------------
  !> 1 次元経度(X)格子点データの X 方向積分(1 層用).
  function IntLon_x(x_data)
    !> 1 次元経度(X)格子点データ
    real(DP), intent(in) :: x_data(0:im-1)
    !> 積分値
    real(DP)             :: IntLon_x

    IntLon_x = sum(x_data * x_Lon_weight)

  end function IntLon_x

  !---------------------------------------------------------------------
  !> 2 次元緯度経度格子点データの緯度(Y)方向積分(1 層用).
  function x_IntLat_xy(xy_data)
    !> 2 次元経度緯度格子点データ(0:im-1,1:jm)
    real(DP), intent(in) :: xy_data(0:im-1,1:jm)
    !> 積分された 1 次元経度(X)格子点データ
    real(DP)             :: x_IntLat_xy(0:im-1)

    integer(8) :: j

    x_IntLat_xy = 0.0D0
    do j=1,jm
      x_IntLat_xy = x_IntLat_xy + xy_data(:,j) * y_Lat_weight(j)
    enddo

  end function x_IntLat_xy

  !---------------------------------------------------------------------
  !> 2 次元緯度経度格子点データの経度(X)方向積分(1 層用).
  function y_IntLon_xy(xy_data)
    !> 2 次元経度緯度格子点データ(0:im-1,1:jm)
    real(DP), intent(in) :: xy_data(0:im-1,1:jm)
    !> 積分された 1 次元緯度(Y)格子点データ
    real(DP)             :: y_IntLon_xy(1:jm)

    integer(8) :: i

    y_IntLon_xy = 0.0D0
    do i=0,im-1
      y_IntLon_xy = y_IntLon_xy + xy_data(i,:) * x_Lon_weight(i)
    enddo

  end function y_IntLon_xy

  !---------------------------------------------------------------------
  !> 2 次元緯度経度格子点データの全領域積分(1 層用).
  function IntLonLat_xy(xy_data)
    !> 2 次元経度緯度格子点データ(0:im-1,1:jm)
    real(DP), intent(in)   :: xy_data(0:im-1,1:jm)
    !> 積分値
    real(DP) :: IntLonLat_xy

    IntLonLat_xy = IntLon_x(x_IntLat_xy(xy_data))

  end function IntLonLat_xy

  !---------------------------------------------------------------------
  !> 1 次元(Y)格子点データの緯度(Y)方向平均(1 層用).
  function AvrLat_y(y_data)
    !>  1 次元緯度格子点データ
    real(DP), intent(in) :: y_data(1:jm)
    !> 平均値
    real(DP)             :: AvrLat_y

    AvrLat_y = IntLat_y(y_data)/sum(y_Lat_weight)

  end function AvrLat_y

  !---------------------------------------------------------------------
  !> 1 次元(X)格子点データの経度(X)方向平均(1 層用).
  function AvrLon_x(x_data)
    !>  1 次元経度(X)格子点データ
    real(DP), intent(in) :: x_data(0:im-1)
    !> 平均値
    real(DP)             :: AvrLon_x

    AvrLon_x = IntLon_x(x_data)/sum(x_Lon_weight)

  end function AvrLon_x

  !---------------------------------------------------------------------
  !> 2 次元緯度経度格子点データの緯度(Y)方向平均(1 層用).
  function x_AvrLat_xy(xy_data)
    !> 2 次元経度緯度格子点データ(0:im-1,1:jm)
    real(DP), intent(in) :: xy_data(0:im-1,1:jm)
    !> 平均された 1 次元経度(X)格子点データ
    real(DP)             :: x_AvrLat_xy(im)

    x_AvrLat_xy = x_IntLat_xy(xy_data)/sum(y_Lat_weight)

  end function x_AvrLat_xy

  !---------------------------------------------------------------------
  !> 2 次元緯度経度格子点データの経度(X)方向平均(1 層用).
  function y_AvrLon_xy(xy_data)
    !> 2 次元経度緯度格子点データ(0:im-1,1:jm)
    real(DP), intent(in) :: xy_data(0:im-1,1:jm)
    !> 平均された 1 次元緯度(Y)格子点
    real(DP)             :: y_AvrLon_xy(1:jm)

    y_AvrLon_xy = y_IntLon_xy(xy_data)/sum(x_Lon_weight)

  end function y_AvrLon_xy

  !---------------------------------------------------------------------
  !> 2 次元緯度経度格子点データの全領域平均(1 層用).
  function AvrLonLat_xy(xy_data)
    !> 2 次元経度緯度格子点データ
    real(DP), intent(in)   :: xy_data(0:im-1,1:jm)
    !> 平均値
    real(DP) :: AvrLonLat_xy

    AvrLonLat_xy = AvrLon_x(x_AvrLat_xy(xy_data))

  end function AvrLonLat_xy


end module w_zonal_module_integral
