!= phy_ground モジュールのテストプログラム
!
!= Test program for "phy_ground"
!
! Authors::   Yasuhiro MORIKAWA
! Version::   $Id: phy_ground_test.f90,v 1.4 2007-09-25 22:32:25 morikawa Exp $
! Tag Name::  $Name: dcpam4-20080427 $
! Copyright:: Copyright (C) GFD Dennou Club, 2007. All rights reserved.
! License::   See COPYRIGHT[link:../../../COPYRIGHT]
!
! <b>Note that Japanese and English are described in parallel.</b>
!
! phy_ground モジュールの動作テストを行うためのプログラムです.
! このプログラムがコンパイルできること, および実行時に
! プログラムが正常終了することを確認してください.
!
! This program checks the operation of "phy_ground" module.
! Confirm compilation and execution of this program.
!

program phy_ground_test
  use phy_ground, only: PHYGRD, Create, Close, &
    & PutLine, initialized, Get
  use dc_test, only: AssertEqual, AssertGreaterThan, AssertLessThan
  use dc_types, only: DP, STRING
  use dc_string, only: StoA
  use dc_args, only: ARGS, Open, HelpMsg, Option, Debug, Help, Strict, Close
  use gt4_history, only: HistoryGet
  implicit none

  !---------------------------------------------------------
  !  実験の表題, モデルの名称, 所属機関名
  !  Title of a experiment, name of model, sub-organ
  !---------------------------------------------------------
  character(*), parameter:: title = &
    & 'phy_ground_test $Name: dcpam4-20080427 $ :: ' // &
    & 'Test program of "phy_ground" module'
  character(*), parameter:: source = &
    & 'dcpam4 ' // &
    & '(See http://www.gfd-dennou.org/library/dcpam)'
  character(*), parameter:: institution = &
    & 'GFD Dennou Club (See http://www.gfd-dennou.org)'

  !---------------------------------------------------------
  !  作業変数
  !  Work variables
  !---------------------------------------------------------
  type(ARGS):: arg            ! コマンドライン引数. 
                              ! Command line arguments
  logical:: OPT_namelist      ! -N, --namelist オプションの有無. 
                              ! Existence of '-N', '--namelist' option
  character(STRING):: VAL_namelist
                              ! -N, --namelist オプションの値. 
                              ! Value of '-N', '--namelist' option
  type(PHYGRD):: phy_grd00, phy_grd01, phy_grd02, phy_grd03
  logical:: err


  integer, parameter:: imax = 32
                              ! 経度格子点数. 
                              ! Number of grid points in longitude
  integer, parameter:: jmax = 16
                              ! 緯度格子点数. 
                              ! Number of grid points in latitude

  real(DP), allocatable:: xy_SurfTemp (:,:)
                              ! 地表面温度. 
                              ! Surface temperature
  real(DP), allocatable:: xy_SurfAlbedo (:,:)
                              ! 地表アルベド. 
                              ! Surface albedo
  real(DP), allocatable:: xy_SurfHumidCoeff (:,:)
                              ! 地表湿潤度. 
                              ! Surface humidity coefficient
  real(DP), allocatable:: xy_SurfRoughLength (:,:)
                              ! 地表粗度長. 
                              ! Surface rough length
  real(DP), allocatable:: xy_SurfHeatCapacity (:,:)
                              ! 地表熱容量. 
                              ! Surface heat capacity
  real(DP), allocatable:: xy_GroundTempFlux (:,:)
                              ! 地中熱フラックス. 
                              ! Ground temperature flux
  integer, allocatable:: xy_SurfCondition (:,:)
                              ! 地表状態. 
                              ! Surface condition

  real(DP), allocatable:: xy_SurfTempAns (:,:)
                              ! 地表面温度. 
                              ! Surface temperature
  real(DP), allocatable:: xy_SurfAlbedoAns (:,:)
                              ! 地表アルベド. 
                              ! Surface albedo
  real(DP), allocatable:: xy_SurfHumidCoeffAns (:,:)
                              ! 地表湿潤度. 
                              ! Surface humidity coefficient
  real(DP), allocatable:: xy_SurfRoughLengthAns (:,:)
                              ! 地表粗度長. 
                              ! Surface rough length
  real(DP), allocatable:: xy_SurfHeatCapacityAns (:,:)
                              ! 地表熱容量. 
                              ! Surface heat capacity
  real(DP), allocatable:: xy_GroundTempFluxAns (:,:)
                              ! 地中熱フラックス. 
                              ! Ground temperature flux
  integer, allocatable:: xy_SurfConditionAns (:,:)
                              ! 地表状態. 
                              ! Surface condition

continue

  !---------------------------------------------------------
  !  コマンドライン引数の処理
  !  Command line arguments handling
  !---------------------------------------------------------
  call Open( arg )
  call HelpMsg( arg, 'Title', title )
  call HelpMsg( arg, 'Usage', &
    & './phy_ground_test [Options]' )
  call HelpMsg( arg, 'Source', source )
  call HelpMsg( arg, 'Institution', institution )
  call Option( arg, StoA('-N', '--namelist'), &
    & OPT_namelist, VAL_namelist, help = "NAMELIST filename" )
  call Debug( arg ) ; call Help( arg ) ; call Strict( arg, severe = .true. )
  call Close( arg )

  !---------------------------------------------------------
  !  初期設定テスト
  !  Initialization test
  !---------------------------------------------------------
  allocate( xy_SurfTemp (0:imax-1, 0:jmax-1) )
  allocate( xy_SurfAlbedo (0:imax-1, 0:jmax-1) )
  allocate( xy_SurfHumidCoeff (0:imax-1, 0:jmax-1) )
  allocate( xy_SurfRoughLength (0:imax-1, 0:jmax-1) )
  allocate( xy_SurfHeatCapacity (0:imax-1, 0:jmax-1) )
  allocate( xy_GroundTempFlux (0:imax-1, 0:jmax-1) )
  allocate( xy_SurfCondition (0:imax-1, 0:jmax-1) )

  allocate( xy_SurfTempAns (0:imax-1, 0:jmax-1) )
  allocate( xy_SurfAlbedoAns (0:imax-1, 0:jmax-1) )
  allocate( xy_SurfHumidCoeffAns (0:imax-1, 0:jmax-1) )
  allocate( xy_SurfRoughLengthAns (0:imax-1, 0:jmax-1) )
  allocate( xy_SurfHeatCapacityAns (0:imax-1, 0:jmax-1) )
  allocate( xy_GroundTempFluxAns (0:imax-1, 0:jmax-1) )
  allocate( xy_SurfConditionAns (0:imax-1, 0:jmax-1) )

  !---------------------------------------------------------
  !  デフォルトのデータセットテスト
  !  Default data set test
  !---------------------------------------------------------
  call Create( phy_grd = phy_grd00, & ! (inout)
    & imax = imax, jmax = jmax )          ! (in)
  call AssertEqual( 'initialization test 1', &
    & answer = .true., check = initialized(phy_grd00) )
  call PutLine( phy_grd = phy_grd00 ) ! (in)

  xy_SurfTempAns         = 273.0_DP
  xy_SurfAlbedoAns       = 0.3_DP
  xy_SurfHumidCoeffAns   = 0.0_DP
  xy_SurfRoughLengthAns  = 0.0_DP
  xy_SurfHeatCapacityAns = 0.0_DP
  xy_GroundTempFluxAns   = 0.0_DP
  xy_SurfConditionAns    = 0

  call Get( phy_grd = phy_grd00, & ! (inout)
    & xy_SurfTemp = xy_SurfTemp, &                  ! (out)
    & xy_SurfAlbedo = xy_SurfAlbedo, &              ! (out)
    & xy_SurfHumidCoeff = xy_SurfHumidCoeff, &      ! (out)
    & xy_SurfRoughLength = xy_SurfRoughLength, &    ! (out)
    & xy_SurfHeatCapacity = xy_SurfHeatCapacity, &  ! (out)
    & xy_GroundTempFlux = xy_GroundTempFlux, &      ! (out)
    & xy_SurfCondition = xy_SurfCondition )         ! (out)

  call AssertGreaterThan( 'default data set (SurfTemp) test 1', &
    & answer = xy_SurfTempAns - 1.0e-10, &
    & check = xy_SurfTemp )
  call AssertLessThan( 'default data set (SurfTemp) test 2', &
    & answer = xy_SurfTempAns + 1.0e-10, &
    & check = xy_SurfTemp )

  call AssertGreaterThan( 'default data set (SurfAlbedo) test 1', &
    & answer = xy_SurfAlbedoAns - 1.0e-10, &
    & check = xy_SurfAlbedo )
  call AssertLessThan( 'default data set (SurfAlbedo) test 2', &
    & answer = xy_SurfAlbedoAns + 1.0e-10, &
    & check = xy_SurfAlbedo )

  call AssertGreaterThan( 'default data set (SurfHumidCoeff) test 1', &
    & answer = xy_SurfHumidCoeffAns - 1.0e-10, &
    & check = xy_SurfHumidCoeff )
  call AssertLessThan( 'default data set (SurfHumidCoeff) test 2', &
    & answer = xy_SurfHumidCoeffAns + 1.0e-10, &
    & check = xy_SurfHumidCoeff )

  call AssertGreaterThan( 'default data set (SurfRoughLength) test 1', &
    & answer = xy_SurfRoughLengthAns - 1.0e-10, &
    & check = xy_SurfRoughLength )
  call AssertLessThan( 'default data set (SurfRoughLength) test 2', &
    & answer = xy_SurfRoughLengthAns + 1.0e-10, &
    & check = xy_SurfRoughLength )

  call AssertGreaterThan( 'default data set (SurfHeatCapacity) test 1', &
    & answer = xy_SurfHeatCapacityAns - 1.0e-10, &
    & check = xy_SurfHeatCapacity )
  call AssertLessThan( 'default data set (SurfHeatCapacity) test 2', &
    & answer = xy_SurfHeatCapacityAns + 1.0e-10, &
    & check = xy_SurfHeatCapacity )

  call AssertGreaterThan( 'default data set (GroundTempFlux) test 1', &
    & answer = xy_GroundTempFluxAns - 1.0e-10, &
    & check = xy_GroundTempFlux )
  call AssertLessThan( 'default data set (GroundTempFlux) test 2', &
    & answer = xy_GroundTempFluxAns + 1.0e-10, &
    & check = xy_GroundTempFlux )

  call AssertEqual( 'default data set (SurfCondition) test', &
    & answer = xy_SurfConditionAns, &
    & check = xy_SurfCondition )

  !---------------------------------------------------------
  !  終了処理テスト
  !  Termination test
  !---------------------------------------------------------
  call Close( phy_grd = phy_grd00 ) ! (inout)
  call AssertEqual( 'termination test 1', &
    & answer = .false., check = initialized(phy_grd00) )
  call PutLine( phy_grd = phy_grd00 ) ! (in)

  !---------------------------------------------------------
  !  引数によるデータセットテスト
  !  Data set with arguments test
  !---------------------------------------------------------
  xy_SurfTempAns         = 273.0_DP
  xy_SurfAlbedoAns       = 0.15_DP
  xy_SurfHumidCoeffAns   = 1.0_DP
  xy_SurfRoughLengthAns  = 0.0001_DP
  xy_SurfHeatCapacityAns = 0.0_DP
  xy_GroundTempFluxAns   = 0.0_DP
  xy_SurfConditionAns    = 0

  call Create( phy_grd = phy_grd01, & ! (inout)
    & imax = imax, jmax = jmax, &         ! (in)
    & SurfTemp = xy_SurfTempAns (0,0), &
    & SurfAlbedo = xy_SurfAlbedoAns (0,0), &
    & SurfHumidCoeff = xy_SurfHumidCoeffAns (0,0), &
    & SurfRoughLength = xy_SurfRoughLengthAns (0,0), &
    & SurfHeatCapacity = xy_SurfHeatCapacityAns (0,0), &
    & GroundTempFlux = xy_GroundTempFluxAns (0,0), &
    & SurfCondition = xy_SurfConditionAns (0,0) )
  call AssertEqual( 'initialization test 2', &
    & answer = .true., check = initialized(phy_grd01) )
  call PutLine( phy_grd = phy_grd01 ) ! (in)

  call Get( phy_grd = phy_grd01, & ! (inout)
    & xy_SurfTemp = xy_SurfTemp, &                  ! (out)
    & xy_SurfAlbedo = xy_SurfAlbedo, &              ! (out)
    & xy_SurfHumidCoeff = xy_SurfHumidCoeff, &      ! (out)
    & xy_SurfRoughLength = xy_SurfRoughLength, &    ! (out)
    & xy_SurfHeatCapacity = xy_SurfHeatCapacity, &  ! (out)
    & xy_GroundTempFlux = xy_GroundTempFlux, &      ! (out)
    & xy_SurfCondition = xy_SurfCondition )         ! (out)

  call AssertGreaterThan( 'data set with arguments (SurfTemp) test 1', &
    & answer = xy_SurfTempAns - 1.0e-10, &
    & check = xy_SurfTemp )
  call AssertLessThan( 'data set with arguments (SurfTemp) test 2', &
    & answer = xy_SurfTempAns + 1.0e-10, &
    & check = xy_SurfTemp )

  call AssertGreaterThan( 'data set with arguments (SurfAlbedo) test 1', &
    & answer = xy_SurfAlbedoAns - 1.0e-10, &
    & check = xy_SurfAlbedo )
  call AssertLessThan( 'data set with arguments (SurfAlbedo) test 2', &
    & answer = xy_SurfAlbedoAns + 1.0e-10, &
    & check = xy_SurfAlbedo )

  call AssertGreaterThan( 'data set with arguments (SurfHumidCoeff) test 1', &
    & answer = xy_SurfHumidCoeffAns - 1.0e-10, &
    & check = xy_SurfHumidCoeff )
  call AssertLessThan( 'data set with arguments (SurfHumidCoeff) test 2', &
    & answer = xy_SurfHumidCoeffAns + 1.0e-10, &
    & check = xy_SurfHumidCoeff )

  call AssertGreaterThan( 'data set with arguments (SurfRoughLength) test 1', &
    & answer = xy_SurfRoughLengthAns - 1.0e-10, &
    & check = xy_SurfRoughLength )
  call AssertLessThan( 'data set with arguments (SurfRoughLength) test 2', &
    & answer = xy_SurfRoughLengthAns + 1.0e-10, &
    & check = xy_SurfRoughLength )

  call AssertGreaterThan( 'data set with arguments (SurfHeatCapacity) test 1', &
    & answer = xy_SurfHeatCapacityAns - 1.0e-10, &
    & check = xy_SurfHeatCapacity )
  call AssertLessThan( 'data set with arguments (SurfHeatCapacity) test 2', &
    & answer = xy_SurfHeatCapacityAns + 1.0e-10, &
    & check = xy_SurfHeatCapacity )

  call AssertGreaterThan( 'data set with arguments (GroundTempFlux) test 1', &
    & answer = xy_GroundTempFluxAns - 1.0e-10, &
    & check = xy_GroundTempFlux )
  call AssertLessThan( 'data set with arguments (GroundTempFlux) test 2', &
    & answer = xy_GroundTempFluxAns + 1.0e-10, &
    & check = xy_GroundTempFlux )

  call AssertEqual( 'data set with arguments (SurfCondition) test', &
    & answer = xy_SurfConditionAns, &
    & check = xy_SurfCondition )

  call Close( phy_grd = phy_grd01 ) ! (inout)
  call AssertEqual( 'termination test 2', &
    & answer = .false., check = initialized(phy_grd01) )

  !---------------------------------------------------------
  !  netCDF ファイル (引数指定) からのデータセットテスト
  !  Data set from netCDF file specified by arguments test
  !---------------------------------------------------------
  call HistoryGet( &
    & file = 'phy_ground_test00.nc', & ! (in)
    & varname = 'SurfTemp', &  ! (in)
    & array = xy_SurfTempAns ) ! (out)

  call Create( phy_grd = phy_grd02, & ! (inout)
    & imax = imax, jmax = jmax, &
    & ground_nc = 'phy_ground_test00.nc', &
    & SurfTemp_varname = 'SurfTemp' )
  call AssertEqual( 'initialization test 3', &
    & answer = .true., check = initialized(phy_grd02) )
  call PutLine( phy_grd = phy_grd02 ) ! (in)

  call Get( phy_grd = phy_grd02, & ! (inout)
    & xy_SurfTemp = xy_SurfTemp )                   ! (out)

  call AssertGreaterThan( 'data set from netCDF file specified by arguments (SurfTemp) test 1', &
    & answer = xy_SurfTempAns - 1.0e-10, &
    & check = xy_SurfTemp )
  call AssertLessThan( 'data set from netCDF file specified by arguments (SurfTemp) test 2', &
    & answer = xy_SurfTempAns + 1.0e-10, &
    & check = xy_SurfTemp )

  call Close( phy_grd = phy_grd02 ) ! (inout)
  call AssertEqual( 'termination test 3', &
    & answer = .false., check = initialized(phy_grd02) )


  !---------------------------------------------------------
  !  netCDF ファイル (NAMELIST ファイルから指定) からのデータセットテスト
  !  Data set from netCDF file specified by NAMELIST file
  !---------------------------------------------------------
  call HistoryGet( &
    & file = 'phy_ground_test00.nc', & ! (in)
    & varname = 'SurfTemp', &  ! (in)
    & array = xy_SurfTempAns ) ! (out)

  call Create( phy_grd = phy_grd03, & ! (inout)
    & imax = imax, jmax = jmax, &
    & nmlfile = VAL_namelist )
  call AssertEqual( 'initialization test 4', &
    & answer = .true., check = initialized(phy_grd03) )
  call PutLine( phy_grd = phy_grd03 ) ! (in)

  call Get( phy_grd = phy_grd03, & ! (inout)
    & xy_SurfTemp = xy_SurfTemp )                   ! (out)

  call AssertGreaterThan( 'data set from netCDF file specified by NAMELIST file (SurfTemp) test 1', &
    & answer = xy_SurfTempAns - 1.0e-10, &
    & check = xy_SurfTemp )
  call AssertLessThan( 'data set from netCDF file specified by NAMELIST file (SurfTemp) test 2', &
    & answer = xy_SurfTempAns + 1.0e-10, &
    & check = xy_SurfTemp )

  call Close( phy_grd = phy_grd03 ) ! (inout)
  call AssertEqual( 'termination test 4', &
    & answer = .false., check = initialized(phy_grd03) )

end program phy_ground_test
