!------------------------------------------------------------------------
! Copyright (c) 2023 SPMODEL Development Group. All rights reserved.
!------------------------------------------------------------------------
!
!表題  ee_mpi_module テストプログラム
!
!履歴  2023/03/06  竹広真一
!
program et_mpi_module_test_integral

  use dc_message, only : MessageNotify
  use dc_test, only : AssertEqual
  use et_mpi_module
  use mpi
  implicit none

  !---- 空間解像度設定 ----
  integer, parameter :: im=32, jm=32            ! 格子点の設定(X,Y)
  integer, parameter :: km=10, lm=21            ! 切断波数の設定(X,Y)

  !---- 変数 ----
  real(8), allocatable :: vx_Data(:,:)          ! 格子データ
  real(8), allocatable :: x_Data(:)             ! 格子データ
  real(8), allocatable :: v_Data(:)             ! 格子データ

  !---- 座標変数など ----
  real(8), parameter :: xmin = -1.0d0, xmax=1.0d0
  real(8), parameter :: ymin = -1.0d0, ymax=1.0d0

  ! 判定誤差設定
  integer, parameter :: check_digits = 10
  integer, parameter :: ignore = -11
  integer :: i, j

  integer            :: np, ip, ierr
  real(8), parameter :: pi=3.1415926535897932385D0

  call MessageNotify('M','ee_mpi_module_intavr_test', &
       'ee_mpi_module integral/average function tests')

  !---------------- MPI スタート ---------------------
  call MPI_INIT(IERR)
  call MPI_COMM_RANK(MPI_COMM_WORLD,IP,IERR)
  call MPI_COMM_SIZE(MPI_COMM_WORLD,NP,IERR)

  !---------------- 座標値の設定 ---------------------
  call et_mpi_initial(im,jm,km,lm,xmin,xmax,ymin,ymax)    ! スペクトル初期化

  allocate(vx_Data(jc(ip),0:im-1))    ! 格子データ
  allocate(x_Data(0:im-1))            ! 格子データ
  allocate(v_Data(jc(ip)))            ! 格子データ

  !------------------- 初期値設定 ----------------------
  vx_Data = sin(pi*vx_X) * cos(pi*vx_Y)
  write(6,*) 'f = sin(pi*X)*cos(pi*Y)'

    call check0d(IntYX_vx(vx_Data),  0.0d0, 'IntYX_vx')
    call check0d(AvrYX_vx(vx_Data),  0.0d0, 'AvrYX_vx')

    call check1d(v_IntX_vx(vx_Data), (/(0.0d0, j=1,jc(ip))/), 'v_IntX_vx')
    call check1d(v_AvrX_vx(vx_Data), (/(0.0d0, j=1,jc(ip))/), 'v_AvrX_vx')

    call check1d(x_IntY_vx(vx_Data), (/(0.0d0, i=0,im-1)/), 'x_IntY_vx')
    call check1d(x_AvrY_vx(vx_Data), (/(0.0d0, i=0,im-1)/), 'x_AvrY_vx')

  vx_Data = (1 - sin(pi*vx_X)) * cos(pi*vx_Y)**2
  write(6,*) 'f = (1-sin(pi*X)) * cos(pi*Y)**2'

    call check0d(IntYX_vx(vx_Data), 2.0d0, 'IntYX_vx')
    call check0d(AvrYX_vx(vx_Data), 5.0d-1, 'AvrYX_vx')

    call check1d(v_IntX_vx(vx_Data), 2.0d0*cos(pi*v_Y)**2, 'y_IntX_vx')
    call check1d(v_AvrX_vx(vx_Data), cos(pi*v_Y)**2, 'y_AvrX_vx')

    call check1d(x_IntY_vx(vx_Data), &
      (1.0d0-sin(pi*x_X)), 'x_IntY_vx')
    call check1d(x_AvrY_vx(vx_Data), &
      (5.0d-1)*(1.0d0-sin(pi*x_X)), 'x_AvrY_vx')

  x_Data = 1 - sin(2*pi*x_X)
  write(6,*) 'f = 1-sin(2*pi*X)'

    call check0d(IntX_x(x_Data), 2.0d0, 'IntX_x')
    call check0d(AvrX_x(x_Data), 1.0d0, 'AvrX_x')

  v_Data = cos(pi*v_Y)**2
  write(6,*) 'f = cos(pi*Y)**2'

    call check0d(IntY_v(v_Data), 1.0d0, 'IntY_y')
    call check0d(AvrY_v(v_Data), 5.0d-1, 'AvrY_y')


  call MPI_FINALIZE(IERR)
  
  call MessageNotify('M','et_mpi_module_test_integral', &
       'et_mpi_module integral/average function tests succeeded!')

contains

  subroutine check1d(var1,sol1,funcname)
    real(8) :: var1(:)                  ! 判定する配列
    real(8) :: sol1(:)                  ! 解析解
    character(len=*) :: funcname        ! 関数名

    call AssertEqual(     &
      message = funcname, &
      answer = sol1,       &
      check = var1,        &
      significant_digits = check_digits, ignore_digits = ignore     )

  end subroutine check1d

  subroutine check0d(var0,sol0,funcname)
    real(8) :: var0                       ! 判定する配列
    real(8) :: sol0                       ! 解析解
    character(len=*) :: funcname          ! 関数名

    call AssertEqual(      &
      message = funcname,  &
      answer = sol0,       &
      check = var0,        &
      significant_digits = check_digits, ignore_digits = ignore     )

  end subroutine check0d

end program et_mpi_module_test_integral
