!----------------------------------------------------------------------
!     Copyright (c) 2011--2012 Shin-ichi Takehiro. All rights reserved.
!----------------------------------------------------------------------
!
!表題  wq_module テストプログラム
!
!      wr_RotRad_wq のテスト (1/r d/dr r)
!      wr_DivRad_wq のテスト (1/r^2 d/dr r^2)
!      wq_Rad2Inv_wq のテスト (1/r^2)
!      wq_Lapla_wq のテスト (1/r^2 d/dr r^2)
!      xyr_GradLon_wq のテスト
!      xyr_GradLat_wq のテスト
!      wq_Div_xyr_xyr_xyr のテスト
!      wr_DivLon_xyr のテスト (1/r cosφ d/dλ)
!      wr_DivLat_xyr のテスト (1/r cosφ d/dφ cosφ)
!      wr_DivRad_xyr のテスト (1/r^2 d/dr r^2)
!      xyr_RotLon_wq_wq のテスト (1/r ∂Vrad/∂φ-1/r ∂(r Vlat)/∂r)
!      xyr_RotLat_wq_wq のテスト (1/r ∂(r Vlon)/∂r - 1/rcosφ・∂Vrad/∂λ)
!      wr_RotRad_xyr_xyr のテスト (1/rcosφ・∂Vlat/∂λ - 1/rcosφ・∂(Vlon cosφ)/∂φ)
!
!
!履歴  2011/09/08  竹広真一  wq_module_deriv1_test.f90 を MPI 用に改造
!      2011/09/12  竹広真一  wtq_mpi_module 用に改造
!      2012/04/02  竹広真一  wtq_mpi_module_sjpack 用に改造
!      2012/04/03  竹広真一  wtq_module_sjpack 用に改造
!      2012/04/03  竹広真一  wtq_module 用に改造
!
program wtq_module_deriv_wq_test1

  use dc_message, only : MessageNotify
  use dc_test, only : AssertEqual
  use wtq_module
  implicit none

  integer,parameter  :: im=32, jm=16         ! 格子点の設定(経度, 緯度, 動径)
  integer,parameter  :: kmo=16, kmi=10       ! 格子点の設定(球殻動径, 球動径)
  integer,parameter  :: nm=10                ! 切断波数の設定(水平)
  integer,parameter  :: lmo=10, lmi=16       ! 切断波数の設定(球殻動径, 球動径)
  real(8),parameter  :: ri=0.5, ro=1.5       ! 内外半径

  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_Data
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_Data1

  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_VLon
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_VLat
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_VRad
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_Psi
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_GradLon
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_GradLat
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_Div
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_DivLon
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_DivLat
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_DivRad
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_RotLon
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_RotLat
  real(8), dimension(0:im-1,1:jm,kmi)     :: xyr_RotRad

  ! 判定誤差設定
  integer, parameter :: check_digits = 8
  integer, parameter :: ignore = -9

  integer, parameter :: nmin=1, nmax=10

  integer :: n

  call MessageNotify('M','wtq_module_derivative_wq_test1', &
       'wtq_module wq-derivative function test #1')

  call wtq_Initial(im,jm,kmi,kmo,nm,lmi,lmo,ri,ro)

  !==================== wr_RotRad_wq ====================

  write( 6,* ) 'Test for wr_RotDRad_wq (even mode)'
  do n=nmin+1,nmax,2
     write(6,*) 'n=',n
     xyr_Data = xyr_Rad**n
     xyr_Data1 = (n+1)*xyr_Rad**(n-1)

     xyr_Data = xyr_wr(wr_RotDRad_wq(wq_xyr(xyr_Data)))

     call AssertEqual(&
       message='wq_RotRad_wq with r^n (even n)',                     &
       answer = xyr_Data1,                                           &
       check = xyr_Data,                                             &
       significant_digits = check_digits, ignore_digits = ignore     &
       )
  enddo

  do n=nmin,nmax,2
     xyr_Data = xyr_Rad**n*cos(xyr_Lat)*sin(xyr_Lon)
     xyr_Data1 = (n+1)*xyr_Rad**(n-1)*cos(xyr_Lat)*sin(xyr_Lon)
     xyr_Data = xyr_wr(wr_RotDRad_wq(wq_xyr(xyr_Data)))

     call AssertEqual(&
       message='wq_RotRad_wq with r^n Y_1^-1 (odd n)',               &
       answer = xyr_Data1,                                           &
       check = xyr_Data,                                             &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  enddo

  !==================== wr_DivRad_wq ====================
  do n=nmin,nmax,2
     write(6,*) 'n=',n
     xyr_Data = xyr_Rad**n * cos(xyr_Lat)*sin(xyr_Lon)
     xyr_Data1 = (n+2)*xyr_Rad**(n-1)*cos(xyr_Lat)*sin(xyr_Lon)

     xyr_Data = xyr_wr(wr_DivRad_wq(wq_xyr(xyr_Data)))

     call AssertEqual(&
       message='wr_DivRad_wq with r^n Y_1^-1 (odd n)',               &
       answer = xyr_Data1,                                           &
       check = xyr_Data,                                             &
       significant_digits = check_digits, ignore_digits = ignore     &
       )
  enddo

  do n=nmin+1,nmax,2
     write(6,*) 'n=',n
     xyr_Data = xyr_Rad**n
     xyr_Data1 = (n+2)*xyr_Rad**(n-1)

     xyr_Data = xyr_wr(wr_DivRad_wq(wq_xyr(xyr_Data)))

     call AssertEqual(&
       message='wr_DivRad_wq with r^n (even n)',                     &
       answer = xyr_Data1,                                           &
       check = xyr_Data,                                             &
       significant_digits = check_digits, ignore_digits = ignore     &
       )
  enddo

  !==================== wq_Rad2Inv_wq ====================
  do n=nmin+2,nmax,2
     write(6,*) 'n=',n
     xyr_Data = xyr_Rad**n * cos(xyr_Lat)*sin(xyr_Lon)
     xyr_Data1 = xyr_Data/xyr_Rad**2

     xyr_Data = xyr_wq(wq_Rad2Inv_wq(wq_xyr(xyr_Data)))

     call AssertEqual(&
       message='wq_Rad2Inv_wq with r^n Y_1^-1 (odd n)',              &
       answer = xyr_Data1,                                           &
       check = xyr_Data,                                             &
       significant_digits = check_digits, ignore_digits = ignore     &
       )
  enddo

  do n=nmin+1,nmax,2
     write(6,*) 'n=',n
     xyr_Data = xyr_Rad**n
     xyr_Data1 = xyr_Data/xyr_Rad**2

     xyr_Data = xyr_wq(wq_Rad2Inv_wq(wq_xyr(xyr_Data)))

     call AssertEqual(&
       message='wq_Rad2Inv_wq with r^n (even n)',                    &
       answer = xyr_Data1,                                           &
       check = xyr_Data,                                             &
       significant_digits = check_digits, ignore_digits = ignore     &
       )
  enddo

  !==================== wq_Lapla_wq ====================
  do n=nmin,nmax,2
     write(6,*) 'n=',n
     xyr_Data = xyr_Rad**n * cos(xyr_Lat)*sin(xyr_Lon)
     xyr_Data1 = (n*(n+1)-2)*xyr_Data/xyr_Rad**2

     xyr_Data = xyr_wq(wq_Lapla_wq(wq_xyr(xyr_Data)))

     call AssertEqual(&
       message='wq_Lapla_wq with r^n Y_1^-1 (odd n)',                &
       answer = xyr_Data1,                                           &
       check = xyr_Data,                                             &
       significant_digits = check_digits, ignore_digits = ignore     &
       )
  enddo

  write( 6,* ) 'Test for wq_Lapla_wq(even mode)'
  do n=nmin+1,nmax,2
     write(6,*) 'n=',n
     xyr_Data = xyr_Rad**n
     xyr_Data1 = n*(n+1)*xyr_Data/xyr_Rad**2

     xyr_Data = xyr_wq(wq_Lapla_wq(wq_xyr(xyr_Data)))

     call AssertEqual(&
       message='wq_Lapla_wq with r^n (even n)',                      &
       answer = xyr_Data1,                                           &
       check = xyr_Data,                                             &
       significant_digits = check_digits, ignore_digits = ignore     &
       )
  enddo

  !========== xyr_GradLon_wq, xyr_GradLat_wq, wr_Div_xyr_xyr_xyr ==========
  n=2

  ! ------ r^3 Y_1^1 Poloidal field -----
  xyr_VRad = 0.0D0
  xyr_Psi = xyr_Rad**(n+1) * cos(xyr_Lat)*sin(xyr_Lon)   ! r**3 P_1^1

  xyr_GradLon =  xyr_Rad**n * cos(xyr_Lon)
  xyr_GradLat = -xyr_Rad**n * sin(xyr_Lat)*sin(xyr_Lon)

  xyr_Div = - 2* xyr_Psi/xyr_Rad**2

  call AssertEqual(&
       message='xyr_GradLon_wq with r^3 Y_1^1',                      &
       answer = xyr_GradLon,                                         &
       check = xyr_GradLon_wq(wq_xyr(xyr_Psi)),                      &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  call AssertEqual(&
       message='xyr_GradLat_wq with r^3 Y_1^1',                      &
       answer = xyr_GradLat,                                         &
       check = xyr_GradLat_wq(wq_xyr(xyr_Psi)),                      &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  call AssertEqual(&
       message='wr_Div_xyr_xyr_xyr with r^3 Y_1^1',                  &
       answer = xyr_Div,                                             &
       check = xyr_wr(wr_Div_xyr_xyr_xyr(xyr_GradLon,xyr_GradLat,xyr_Vrad)), &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  ! ------ r^2 Y_2^1 Poloidal field -----
  xyr_VRad = 0.0D0
  xyr_Psi = xyr_Rad**n * cos(xyr_Lat)*sin(xyr_Lat) * sin(xyr_Lon) ! P_2^1

  xyr_GradLon =  xyr_Rad**(n-1)*sin(xyr_Lat)*cos(xyr_Lon)
  xyr_GradLat =  xyr_Rad**(n-1)*cos(2*xyr_Lat)*sin(xyr_Lon)

  xyr_Div = - 6* xyr_Psi/xyr_Rad**2

  call AssertEqual(&
       message='xyr_GradLon_wq with r^2 Y_2^1',                      &
       answer = xyr_GradLon,                                         &
       check = xyr_GradLon_wq(wq_xyr(xyr_Psi)),                      &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  call AssertEqual(&
       message='xyr_GradLat_wq with r^2 Y_2^1',                      &
       answer = xyr_GradLat,                                         &
       check = xyr_GradLat_wq(wq_xyr(xyr_Psi)),                      &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  call AssertEqual(&
       message='wr_Div_xyr_xyr_xyr with r^2 Y_2^1',                  &
       answer = xyr_Div,                                             &
       check = xyr_wr(wr_Div_xyr_xyr_xyr(xyr_GradLon,xyr_GradLat,xyr_Vrad)), &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  !========== wr_DivLon_xyr, wr_DivLat_xyr, wr_DivRad_xyr ==========

  xyr_VLon   = xyr_rad**n * cos(xyr_Lat)**2*sin(xyr_Lon)
  xyr_DivLon = xyr_rad**(n-1)*cos(xyr_Lat)*cos(xyr_Lon)

  xyr_VLat   = xyr_rad**n * cos(xyr_Lat)**2*sin(xyr_Lon)
  xyr_DivLat = -3*xyr_rad**(n-1)*cos(xyr_Lat)*sin(xyr_Lat)*sin(xyr_Lon)

  xyr_VRad = xyr_Rad**n * cos(xyr_Lat)*sin(xyr_Lon)
  xyr_DivRad = (n+2)*xyr_Rad**(n-1)*cos(xyr_Lat)*sin(xyr_Lon)

  call AssertEqual(&
       message='wr_DivLon_xyr',                                      &
       answer = xyr_DivLon,                                          &
       check = xyr_wr(wr_DivLon_xyr(xyr_VLon)),                      &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  call AssertEqual(&
       message='wr_DivLat_xyr',                                      &
       answer = xyr_DivLat,                                          &
       check = xyr_wr(wr_DivLat_xyr(xyr_VLat)),                      &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  call AssertEqual(&
       message='wr_DivRad_xyr',                                      &
       answer = xyr_DivRad,                                          &
       check = xyr_wr(wr_DivRad_xyr(xyr_VRad)),                      &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  !========== xyr_RotLon_wq_wq, xyr_DivLat_wq_wq, wr_DivRad_xyr_xyr ==========
  n=3

  xyr_VLon = xyr_rad**n * cos(xyr_Lat)*sin(xyr_Lon)
  xyr_VLat = xyr_rad**n * cos(xyr_Lat)*sin(xyr_Lon)
  xyr_VRad = xyr_Rad**n * cos(xyr_Lat)*sin(xyr_Lon)

  xyr_RotLon = - xyr_rad**(n-1) * sin(xyr_Lat) * sin(xyr_Lon)  &
               - (n+1)*xyr_rad**(n-1)*cos(xyr_Lat)*sin(xyr_Lon)

  xyr_RotLat =   (n+1)*xyr_rad**(n-1)*cos(xyr_Lat)*sin(xyr_Lon) &
               - xyr_rad**(n-1) * cos(xyr_Lon) 

  call AssertEqual(&
       message='xyr_RotLon_wq_wq',                                   &
       answer = xyr_RotLon,                                          &
       check = xyr_RotLon_wq_wq(wq_xyr(xyr_VRad),wq_xyr(xyr_VLat)),  &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  call AssertEqual(&
       message='xyr_RotLat_wq_wq',                                   &
       answer = xyr_RotLat,                                          &
       check = xyr_RotLat_wq_wq(wq_xyr(xyr_VLon),wq_xyr(xyr_VRad)),  &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  xyr_VLon = xyr_rad**n * cos(xyr_Lat) 
  xyr_VLat = xyr_rad**n * cos(xyr_Lat)**2 * sin(xyr_Lon)

  xyr_RotRad =   xyr_rad**(n-1) * cos(xyr_Lat) * cos(xyr_Lon) &
               + 2 * xyr_rad**(n-1) * sin(xyr_Lat) 

  call AssertEqual(&
       message='wr_RotRad_xyr_xyr',                                  &
       answer = xyr_RotRad,                                          &
       check = xyr_wr(wr_RotRad_xyr_xyr(xyr_VLat,xyr_VLon)),         &
       significant_digits = check_digits, ignore_digits = ignore     &
       )

  call MessageNotify('M','wq_module_derivative_wq_test1', &
       'wq_module wq-derivative function test #1 succeeded!')

end program wtq_module_deriv_wq_test1
