!= 力学過程 (スペクトル法, Arakawa and Suarez (1983))
!
!= Dynamical process (Spectral method, Arakawa and Suarez (1983))
!
! Authors::   Yasuhiro MORIKAWA
! Version::   $Id: $ 
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2008. All rights reserved.
! License::   See COPYRIGHT[link:../../../COPYRIGHT]
!

module dyn_hspl_vas83
  !
  != 力学過程 (スペクトル法, Arakawa and Suarez (1983))
  !
  != Dynamical Core (Spectral method, Arakawa and Suarez (1983))
  !
  ! <b>Note that Japanese and English are described in parallel.</b>
  !
  ! 力学過程を演算するモジュールです. 
  ! 水平離散化にスペクトル法を, 鉛直離散化には Arakawa and Suarez (1983)
  ! を用いています.
  !
  ! 時間積分法にはリープフロッグスキームを用いています.
  ! デフォルトでは, $ \Delta t $ を大きくとるために, 重力波項に 
  ! セミインプリシット法を適用しています.
  ! 重力波項をエクスプリシット法によって解くことも可能です.
  !
  ! This is a dynamical core module. Spectral method (for horizontal) and 
  ! Arakawa and Suarez (1983) method (for vertical) are used.
  !
  ! Leap-frog scheme is used as time integration. 
  ! By default, semi-implicit scheme is applied to gravitational terms 
  ! for extension of $ \Delta t $ . 
  ! Explicit scheme can be applied to gravitational terms. 

  ! モジュール引用 ; USE statements
  !

  ! 種別型パラメタ
  ! Kind type parameter
  !
  use dc_types, only: DP     ! 倍精度実数型. Double precision. 

  ! 宣言文 ; Declaration statements
  !
  implicit none
  private

  ! 公開手続き
  ! Public procedure
  !
  public:: Dynamics

  ! 公開変数
  ! Public variables
  !
  logical, save, public:: dyn_hspl_vas83_inited = .false.
                              ! 初期設定フラグ. 
                              ! Initialization flag

  ! 非公開変数
  ! Private variables
  !
!  namelist /dynamics_nml/

  character(*), parameter:: module_name = 'dynamics'
                              ! モジュールの名称. 
                              ! Module name
  character(*), parameter:: version = &
    & '$Name:  $' // &
    & '$Id:  $'
                              ! モジュールのバージョン
                              ! Module version

  ! INTERFACE 文 ; INTERFACE statements
  !
  interface Dynamics
    module procedure Dynamics
  end interface

contains

  subroutine Dynamics( &
    & xyz_UB,   xyz_VB,   xyz_TempB,   xyz_QVapB,   xy_PsB, &   ! (in)
    & xyz_UN,   xyz_VN,   xyz_TempN,   xyz_QVapN,   xy_PsN, &   ! (in)
    & xyz_DUDt, xyz_DVDt, xyz_DTempDt, xyz_DQVapDt, &           ! (in)
    & xyz_UA,   xyz_VA,   xyz_TempA,   xyz_QVapA,   xy_PsA  &   ! (out)
    & )
    !
    ! 力学過程の演算を行い, 与えられた $ t-\Delta t $ および $ t $ の
    ! 東西風速 (xyz_UB, xyz_VN), 南北風速 (xyz_VB, xyz_VN), 
    ! 温度 (xyz_TempB, xyz_TempN), 比湿 (xyz_QVapB, xyz_QVapN), 
    ! 地表面気圧 (xyz_PsB, xyz_PsN) から, 
    ! $ t+\Delta t $ の
    ! 東西風速 (xyz_UA), 南北風速 (xyz_VA), 温度 (xyz_TempA), 
    ! 比湿 (xyz_QVapA), 地表面気圧 (xyz_PsA) を返します.
    !
    ! 別の物理プロセスによる渦度, 発散, 温度, 比湿の変化を, 
    ! 力学過程の変化に足して次のステップを計算する場合には, 
    ! それらの変化を xyz_DUDt, xyz_DVDt, xyz_DTempDt, xyz_DQVapDt
    ! に与えてください. 
    !
    ! 時間積分法にはリープフロッグスキームを用いています.
    ! デフォルトでは, $ \Delta t $ を大きくとるために, 重力波項に 
    ! セミインプリシット法を適用しています.
    !--
    ! ただし, *time_integration_scheme* に
    ! "Explicit" を指定した場合には重力波項もエクスプリシット法によって
    ! 解きます.
    !++
    !
    ! Calculating dynamical core, 
    ! from eastward wind (xyz_UB, xyz_UN), 
    ! northward wind (xyz_VB, xyz_VN), 
    ! temperature (xyz_TempB, xyz_TempN), 
    ! specific humidity (xyz_QVapB, xyz_QVapN), 
    ! surface pressure (xyz_PsB, xyz_PsN) at $ t-\Delta t $ and $ t $, 
    ! eastward wind (xyz_UA), northward wind (xyz_VA), 
    ! temperature (xyz_TempA), 
    ! specific humidity (xyz_QVapA), surface pressure (xyz_PsA) 
    ! are returned.
    !
    ! In order to add tendencies of vorticity, divergence, 
    ! temperature and specific humidity by another physical process to 
    ! tendencies of this dynamical process 
    ! and to calculate the values at next time step, 
    ! give these tendencies to 
    ! "xyz_DUDt", "xyz_DVDt", "xyz_DTempDt", "xyz_DQVapDt"
    !
    ! Leap-frog scheme is used as time integration. 
    ! By default, semi-implicit scheme is applied to gravitational terms 
    ! for extension of $ \Delta t $ . 
    !--
    ! If "Explicit" is specified to *time_integration_scheme* in "Create", 
    ! explicit scheme is applied to gravitational terms as well as 
    ! other terms.
    !++
    !

    ! モジュール引用 ; USE statements
    !

    ! 格子点設定
    ! Grid points settings
    !
    use gridset, only: imax, & ! 経度格子点数. 
                               ! Number of grid points in longitude
      &                jmax, & ! 緯度格子点数. 
                               ! Number of grid points in latitude
      &                kmax    ! 鉛直層数. 
                               ! Number of vertical level

    ! 種別型パラメタ
    ! Kind type parameter
    !
    use dc_types, only: DP      ! 倍精度実数型. Double precision. 

    ! 宣言文 ; Declaration statements
    !
    implicit none

    real(DP), intent(in):: xyz_UB    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ u (t-\Delta t) $ .   東西風速. Eastward wind
    real(DP), intent(in):: xyz_VB    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ v (t-\Delta t) $ .   南北風速. Northward wind
    real(DP), intent(in):: xyz_TempB (0:imax-1, 1:jmax, 1:kmax)
                              ! $ T (t-\Delta t) $ .   温度. Temperature
    real(DP), intent(in):: xyz_QVapB (0:imax-1, 1:jmax, 1:kmax)
                              ! $ q (t-\Delta t) $ .   比湿. Specific humidity
    real(DP), intent(in):: xy_PsB    (0:imax-1, 1:jmax)
                              ! $ p_s (t-\Delta t) $ . 地表面気圧. Surface pressure

    real(DP), intent(in):: xyz_UN   (0:imax-1, 1:jmax, 1:kmax)
                              ! $ u (t) $ .     東西風速. Eastward wind
    real(DP), intent(in):: xyz_VN   (0:imax-1, 1:jmax, 1:kmax)
                              ! $ v (t) $ .     南北風速. Northward wind
    real(DP), intent(in):: xyz_TempN (0:imax-1, 1:jmax, 1:kmax)
                              ! $ T (t) $ .     温度. Temperature
    real(DP), intent(in):: xyz_QVapN (0:imax-1, 1:jmax, 1:kmax)
                              ! $ q (t) $ .     比湿. Specific humidity
    real(DP), intent(in):: xy_PsN    (0:imax-1, 1:jmax)
                              ! $ p_s (t) $ .   地表面気圧. Surface pressure

    real(DP), intent(in):: xyz_DUDt    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \DP{u}{t} $ . 東西風速変化. 
                              ! Zonal wind tendency
    real(DP), intent(in):: xyz_DVDt    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \DP{v}{t} $ . 南北風速変化. 
                              ! Meridional wind tendency
    real(DP), intent(in):: xyz_DTempDt (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \DP{T}{t} $ . 温度変化. 
                              ! Temperature tendency
    real(DP), intent(in):: xyz_DQVapDt (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \DP{q}{t} $ . 比湿変化. 
                              ! Temperature tendency

    real(DP), intent(out):: xyz_UA    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ u (t+\Delta t) $ .   東西風速. Eastward wind
    real(DP), intent(out):: xyz_VA    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ v (t+\Delta t) $ .   南北風速. Northward wind
    real(DP), intent(out):: xyz_TempA (0:imax-1, 1:jmax, 1:kmax)
                              ! $ T (t+\Delta t) $ .   温度. Temperature
    real(DP), intent(out):: xyz_QVapA (0:imax-1, 1:jmax, 1:kmax)
                              ! $ q (t+\Delta t) $ .   比湿. Specific humidity
    real(DP), intent(out):: xy_PsA    (0:imax-1, 1:jmax)
                              ! $ p_s (t+\Delta t) $ . 地表面気圧. Surface pressure

    character(*), parameter:: subname = 'Dynamics'

    ! 実行文 ; Executable statement
    !

    ! 初期化
    ! Initialization
    !
    if ( .not. dyn_hspl_vas83_inited ) call DynamicsInit

    xyz_UA    = xyz_UN    
    xyz_VA    = xyz_VN    
    xyz_TempA = xyz_TempN 
    xyz_QVapA = xyz_QVapN 
    xy_PsA    = xy_PsN    

  end subroutine Dynamics

  subroutine DynamicsInit

    ! NAMELIST ファイル入力に関するユーティリティ
    ! Utilities for NAMELIST file input
    !
    use namelist_util, only: namelist_filename, NmlutilMsg

    ! ファイル入出力補助
    ! File I/O support
    !
    use dc_iounit, only: FileOpen

    ! 種別型パラメタ
    ! Kind type parameter
    !
    use dc_types, only: STDOUT ! 標準出力の装置番号. Unit number of standard output

    ! メッセージ出力
    ! Message output
    !
    use dc_message, only: MessageNotify

    implicit none

    integer:: unit_nml        ! NAMELIST ファイルオープン用装置番号. 
                              ! Unit number for NAMELIST file open
    integer:: iostat_nml      ! NAMELIST 読み込み時の IOSTAT. 
                              ! IOSTAT of NAMELIST read

    character(*), parameter:: subname = 'DynamicsInit'

    ! 実行文 ; Executable statement
    !

    if ( dyn_hspl_vas83_inited ) return

    call InitCheck

    ! XXXXX の設定
    ! XXXXX settings
    !
!!$    if ( trim(namelist_filename) /= '' ) then
!!$      call FileOpen( unit_nml, &          ! (out)
!!$        & namelist_filename, mode = 'r' ) ! (in)
!!$
!!$      rewind( unit_nml )
!!$      read( unit_nml, &         ! (in)
!!$        & nml = dynamics_nml, &  ! (out)
!!$        & iostat = iostat_nml ) ! (out)
!!$      close( unit_nml )
!!$
!!$      call NmlutilMsg( iostat_nml, module_name ) ! (in)
!!$    end if

    ! XXXXX のチェック
    ! Check XXXXXX
    !
!!$    if ( imax < 1 .or. jmax < 1 .or. kmax < 1 ) then
!!$      call MessageNotify( 'E', subname, &
!!$        & 'number of grid points must be more than 0 ' // &
!!$        & 'imax=%d, jmax=%d, kmax=%d' , &
!!$        & i = (/ imax, jmax, kmax /) )
!!$    end if

    ! 印字 ; Print
    !
!!$    call MessageNotify( 'M', subname, 'imax = %d', i = (/ imax /) )
!!$    call MessageNotify( 'M', subname, 'jmax = %d', i = (/ jmax /) )
!!$    call MessageNotify( 'M', subname, 'kmax = %d', i = (/ kmax /) )
!!$    call MessageNotify( 'M', subname, 'r_Sigma = %*f', &
!!$      &                 d = (/ r_Sigma(0:kmax) /), n = (/ kmax + 1 /) )


    dyn_hspl_vas83_inited = .true.
  end subroutine DynamicsInit

  subroutine InitCheck
    !
    ! 依存モジュールの初期化チェック
    !
    ! Check initialization of dependency modules

    ! モジュール引用 ; USE statements
    !

    ! NAMELIST ファイル入力に関するユーティリティ
    ! Utilities for NAMELIST file input
    !
    use namelist_util, only: namelist_util_inited

    ! 格子点設定
    ! Grid points settings
    !
    use gridset, only: gridset_inited

    ! 物理定数設定
    ! Physical constants settings
    !
    use constants, only: constants_inited

    ! 座標データ設定
    ! Axes data settings
    !
    use axesset, only: axesset_inited

    ! 時刻管理
    ! Time control
    !
    use timeset, only: timeset_inited

    ! メッセージ出力
    ! Message output
    !
    use dc_message, only: MessageNotify

    ! 実行文 ; Executable statement
    !

    if ( .not. namelist_util_inited ) &
      & call MessageNotify( 'E', module_name, '"namelist_util" module is not initialized.' )

    if ( .not. gridset_inited ) &
      & call MessageNotify( 'E', module_name, '"gridset" module is not initialized.' )

    if ( .not. constants_inited ) &
      & call MessageNotify( 'E', module_name, '"constants" module is not initialized.' )

    if ( .not. axesset_inited ) &
      & call MessageNotify( 'E', module_name, '"axesset" module is not initialized.' )

    if ( .not. timeset_inited ) &
      & call MessageNotify( 'E', module_name, '"timeset" module is not initialized.' )

  end subroutine InitCheck

end module dyn_hspl_vas83
