!== 水惑星実験 (APE; Aqua Planet Experiment) テストプログラム
!
! Authors::   Yukiko YAMADA, Masaki ISHIWATARI
! Version::   $Id: dcpam_ape.f90,v 1.2 2006/08/21 07:52:12 morikawa Exp $
! Tag Name::  $Name: dcpam3-20070608 $
! Copyright:: Copyright (C) GFD Dennou Club, 2005. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!

program dcpam_ape
  !
  !dcpam のテストプログラムとしての水惑星実験 
  !(APE; Aqua Planet Experiment) を行なうプログラムです.
  !現在は main/init.f90 によって初期値を生成する
  !必要があります.
  !

  !----- NAMELIST 名設定モジュール -----
  use nmlfile_mod, only: nmlfile_init, nmlfile_open, nmlfile_close

  !----- 物理定数設定モジュール -----
  use constants_mod, only: SecPerDay

  !----- 構造体参照モジュール -----
  use dycore_type_mod, only: DYCORE_VARS, DYCORE_DIMS, STRING, INTKIND, REKIND

  !----- 格子点取得モジュール -----
  use dycore_grid_mod, only: dycore_grid_init, dycore_grid_end, &
       &                     im, jm, km, nm

  !----- データI/Oモジュール -----
  use dycore_in_mod,   only: dycore_in_init,                  &
       &                     dycore_in_dims, dycore_in_vars,  &
       &                     dycore_in_end
  use dycore_out_mod,  only: dycore_out_init, dycore_out_put, &
       &                     dycore_out_end

  !----- 力学過程モジュール (DCPAM-APE 力学メインモジュール) -----
  use dcpam_ape_dynamics_mod, only: dcpam_ape_dynamics

  !----- 物理過程モジュール (DCPAM-APE 物理メインモジュール) -----
  use dcpam_ape_physics_mod, only: dcpam_ape_physics

  !----- 力学過程モジュール (スペクトルモデル用) -----
  use dycore_dynamics_mod, only: dycore_dynamics_init, &
       &                         dycore_dynamics_end

  !----- 時間更新・タイムフィルターモジュール -----
  use dycore_time_mod, only: dycore_time_init, dycore_time_progress, &
       &                     dycore_time_end,  dycore_time_filter,   &
       &                     StepInterval, OutputStep, &
       &                     CurrentLoop, CurrentTime, DelTime

  !----- データ I/O ツール -----
    use io_gt4_out_mod , only: io_gt4_out_SetVars

  !----- コマンドライン引数解析ツール -----
  use dc_args, only: ARGS, Open, Debug, Help, Strict, Close

  !----- デバッグ・汎用ツール -----
  use dc_trace,  only: SetDebug, DbgMessage, BeginSub, EndSub
  use dc_message,only: MessageNotify
  use dc_string, only: toChar, Printf

  implicit none

  logical :: CalcDynamics    = .true.  ! 力学コアの演算
  logical :: CalcDiffusion   = .true.  ! 拡散項の演算
  logical :: CalcHS94forcing = .false. ! Held and Suarez(1994) による強制

  namelist /dcpam_ape_nml/ CalcDynamics, CalcDiffusion, CalcHS94forcing
    ! 実験設定を行う。

  !-------------------------------------------------------------------
  !   変数定義
  !-------------------------------------------------------------------
  !----- 次元データ全てを包括 (時間次元のみ除く) -----
  type(DYCORE_DIMS)          :: Dims       ! 次元データ全種

  !----- 計算される格子点データ全てを包括 -----
  type(DYCORE_VARS)          :: Vars_b     ! 格子点データ全種(t-Δt)
  type(DYCORE_VARS)          :: Vars_n     ! 格子点データ全種(t)
  type(DYCORE_VARS)          :: Vars_a     ! 格子点データ全種(t+Δt)

  !----- 作業変数 -----
  !for time measure in temporarily
  real(REKIND) :: &
       & start_time_init, end_time_init, &
       & start_time_dynmcs, end_time_dynmcs, store_time_dynmcs = 0.0, &
       & start_time_physics, end_time_physics, store_time_physics = 0.0
  integer(INTKIND) :: dateval(1:8)

  !for nmlfile_mod
  integer(INTKIND)   :: nmlstat, nmlunit
  logical            :: nmlreadable

  !for dc_args
  type(ARGS) :: arg

  character(*), parameter:: version = &
    & '$Name: dcpam3-20070608 $' // &
    & '$Id: dcpam_ape.f90,v 1.2 2006/08/21 07:52:12 morikawa Exp $'
  character(STRING),  parameter:: subname = "dcpam_ape"

continue
  !-------------------------------------------------------------------
  !   デバッグモード開始
  !-------------------------------------------------------------------
  call Open(arg)
  call Debug(arg); call Help(arg) ; call Strict(arg)
  call Close(arg)

  call BeginSub(subname, version=version)

  !-------------------------------------------------------------------
  !   use CPU_TIME
  !-------------------------------------------------------------------
  call cpu_time(start_time_init)

  !-------------------------------------------------------------------
  !   NAMELIST file Setting
  !-------------------------------------------------------------------
  call nmlfile_init('dcpam_ape.nml')

  !----------------------------------------------------------------
  !   Read init_nml
  !----------------------------------------------------------------
  call nmlfile_open(nmlunit, nmlreadable)
  if (nmlreadable) then
     read(nmlunit, nml=dcpam_ape_nml, iostat=nmlstat)
     call DbgMessage('Stat of NAMELIST dcpam_ape_nml Input is <%d>', &
          &           i=(/nmlstat/))
     write(0, nml=dcpam_ape_nml)
  else
     call DbgMessage('Not Read NAMELIST dcpam_ape_nml')
     call MessageNotify('W', subname, &
          & 'Can not Read NAMELIST dcpam_ape_nml. Force Use Default Value.')
  end if
  call nmlfile_close

  !-------------------------------------------------------------------
  !   格子点数の取得
  !-------------------------------------------------------------------
  call dycore_grid_init

  !-------------------------------------------------------------------
  !   初期値データ読み込み (gt4f90io の上位モジュール)
  !     (ファイル名や読み込む変数は NAMELIST で変更)
  !-------------------------------------------------------------------
  call dycore_in_init
  call dycore_in_dims(  &
       & Dims          )  ! intent(out): 次元データ全種

  call dycore_in_vars( &
       & Vars_b      , & ! intent(out): 格子点データ全種(t-Δt)
       & Vars_n    )     ! intent(out): 格子点データ全種(t)

  !-------------------------------------------------------------------
  !   時間・ ステップに関する初期設定
  !-------------------------------------------------------------------
  call dycore_time_init

  !-------------------------------------------------------------------
  !   データ出力の初期設定
  !-------------------------------------------------------------------
  call dycore_out_init( &
       & Dims           ) ! intent(in): 次元データ全種

  ! -- 物理過程の分 -- 
  call io_gt4_out_SetVars('GeoPot')
  call io_gt4_out_SetVars('Press')
  call io_gt4_out_SetVars('Rain')
  call io_gt4_out_SetVars('DPsDt')
  call io_gt4_out_SetVars('DNegQvapDt')
  call io_gt4_out_SetVars('DLscQvapDt')
  call io_gt4_out_SetVars('DLscTempDt')
  call io_gt4_out_SetVars('LscRain')
  call io_gt4_out_SetVars('DCumulusQvapDt')
  call io_gt4_out_SetVars('DCumulusTempDt')
  call io_gt4_out_SetVars('CumulusRain')
  call io_gt4_out_SetVars('DDryTempDt')
  call io_gt4_out_SetVars('SurfTemp')
  call io_gt4_out_SetVars('DRadLTempDt')
  call io_gt4_out_SetVars('DRadSTempDt')
  call io_gt4_out_SetVars('DVerdiffVelLonDt')
  call io_gt4_out_SetVars('DVerdiffVelLatDt')
  call io_gt4_out_SetVars('DVerdiffTempDt')
  call io_gt4_out_SetVars('DVerdiffQvapDt')

  !-------------------------------------------------------------------
  !   力学過程演算の初期設定
  !-------------------------------------------------------------------
  call dycore_dynamics_init( &
       & Dims              , & ! intent(in): 次元データ全種
       & Vars_a          )     ! intent(out): 格子点データ全種(t+Δt)

  !-------------------------------------------------------------------
  !   use CPU_TIME
  !-------------------------------------------------------------------
  call cpu_time(end_time_init)
  call date_and_time(values=dateval)
  call Printf(6, &
       & 'Elapsed Time=<%r>, Start=<%r>, Stop=<%r>, ' // &
       & 'Now=<%d/%d/%d  %d:%d:%d>', &
       & r=(/end_time_init - start_time_init, &
       &     start_time_init, end_time_init/), &
       & i=(/dateval(1), dateval(2), dateval(3), &
       &     dateval(5), dateval(6), dateval(7)  /) )


  !-------------------------------------------------------------------
  !   メインループ
  !-------------------------------------------------------------------
  MainLoop : do
     call BeginSub( subname, &
          & 'MainLoop : CurrentLoop=<%d>, CurrentTime=<%f>', &
          & i=(/CurrentLoop/), d=(/CurrentTime/) )

     !----------------------------------------------------------------
     !   力学過程演算
     !----------------------------------------------------------------
     call cpu_time(start_time_dynmcs)
     call dcpam_ape_dynamics( &
          & Dims          , &   ! intent(in)   : 次元データ全種
          & Vars_b        , &   ! intent(in)   : 格子点データ全種(t-Δt)
          & Vars_n        , &   ! intent(in)   : 格子点データ全種(t)
          & Vars_a  )           ! intent(inout): 格子点データ全種(t+Δt)
     call cpu_time(end_time_dynmcs)
     
     !----------------------------------------------------------------
     !   物理過程演算
     !----------------------------------------------------------------
     call cpu_time(start_time_physics)
     call dcpam_ape_physics(  &
          & Dims          , &   ! intent(in)   : 次元データ全種
          & Vars_a  )           ! intent(inout): 格子点データ全種(t+Δt)
     call cpu_time(end_time_physics)

     !----------------------------------------------------------------
     !   タイムフィルター
     !----------------------------------------------------------------
     call dycore_time_filter( &
       & Vars_b           , & ! intent(in)   : 格子点データ全種(t-Δt)
       & Vars_n           , & ! intent(inout): 格子点データ全種(t)
       & Vars_a  )            ! intent(in)   : 格子点データ全種(t+Δt)

     !----------------------------------------------------------------
     !   データの出力
     !----------------------------------------------------------------
     call dycore_out_put( &
       & Vars_n  )            ! intent(in): 格子点データ全種(t)

     !----------------------------------------------------------------
     !   時刻更新
     !----------------------------------------------------------------
     call dycore_time_progress( &
       & Vars_b           , & ! intent(inout): 格子点データ全種(t-Δt)
       & Vars_n           , & ! intent(inout): 格子点データ全種(t)
       & Vars_a  )            ! intent(inout): 格子点データ全種(t+Δt)

     !-------------------------------------------------------------------
     !   use CPU_TIME
     !-------------------------------------------------------------------
     store_time_physics = store_time_physics &
          & + (end_time_physics - start_time_physics)
     store_time_dynmcs = store_time_dynmcs &
          & + (end_time_dynmcs - start_time_dynmcs)

     if ( mod(CurrentLoop, StepInterval) == 0 ) then
        call Printf(6, '')
        call Printf(6, '-- ***              ***  ')
        call Printf(6, '-- *** TIME         ***  ')
        call Printf(6, '-- ***      KEEPING ***  ')
        call Printf(6, '-- ***              ***  ')
        call Printf(6, &
             & '--CurrentLoop=<%d>, CurrentTime=<%f>, Day=<%f>', &
             & i=(/CurrentLoop/), d=(/CurrentTime, CurrentTime/SecPerDay /) )
        
        call Printf(6, '--Remaining Loop  ' // &
             & ': RemainingLoop=<%d>, RemainingTime=<%f>, Day=<%f>', &
             & i=(/StepInterval * OutputStep - CurrentLoop/), &
             & d=(/StepInterval * OutputStep * DelTime - CurrentTime , &
             &     ( StepInterval * OutputStep * DelTime &
             &        - CurrentTime ) / SecPerDay /)    )

        call date_and_time(values=dateval)
        call Printf(6, '--Current Time <%d/%d/%d  %d:%d:%d>', &
             & i=(/dateval(1), dateval(2), dateval(3), &
             &     dateval(5), dateval(6), dateval(7)  /) )

        call Printf(6, '--[Categoly]  : [Stored]       ' //  &
             &          '[Current]      [Start]        [Stop] '  )

        call Printf(6, '--Dynamics    : <%r> <%r> <%r> <%r> ',  &
             & r=(/store_time_dynmcs, &
             &     end_time_dynmcs - start_time_dynmcs, &
             &     start_time_dynmcs, end_time_dynmcs/)   )

        call Printf(6, '--Physics   : <%r> <%r> <%r> <%r> ',  &
             & r=(/store_time_physics, &
             &     end_time_physics - start_time_physics, &
             &     start_time_physics, end_time_physics/)   )

     end if

     !----------------------------------------------------------------
     !   ループから抜け出すかどうかの判定
     !----------------------------------------------------------------
     if ( CurrentLoop > StepInterval * OutputStep ) then
        exit MainLoop
     endif

     call EndSub(subname)
  enddo MainLoop

  call dycore_out_end

  call EndSub(subname)
end program dcpam_ape











