!---------------------------------------------------------------------
!     Copyright (C) GFD Dennou Club, 2005. All rights reserved.
!---------------------------------------------------------------------
                                                                 !=begin
!= Module dycore_dynamics_mod
!
!   * Developers: Morikawa Yasuhiro
!   * Version: $Id: dycore_dynamics.f90,v 1.1.1.1 2005/11/08 14:10:24 morikawa Exp $
!   * Tag Name: $Name:  $
!   * Change History: 
!
!== Overview
!
!Call ((< dynamics_mod >))
!
!== Error Handling
!
!== Known Bugs
!
!== Note
!
!== Future Plans
!
!
                                                                 !=end
module dycore_dynamics_mod
                                                                 !=begin
  !== Dependency
  use type_mod,      only : STRING
                                                                 !=end
  implicit none
                                                                 !=begin
  !== Public Interface
  private
  public :: dycore_dynamics_init       ! subroutines
  public :: dycore_dynamics_prediction ! subroutines
  public :: dycore_dynamics_diagnostic ! subroutines
  public :: dycore_dynamics_diffusion  ! subroutines
  public :: dycore_dynamics_end        ! subroutines
                                                                 !=end

  logical, save :: dycore_dynamics_initialized = .false.
  character(STRING),parameter:: version = &
       & '$Id: dycore_dynamics.f90,v 1.1.1.1 2005/11/08 14:10:24 morikawa Exp $'
  character(STRING),parameter:: tagname = '$Name:  $'

contains

                                                                 !=begin
  !== Procedure Interface
  !
  !=== Initialize module and
  !
  !((< dynamics_mod >)) を初期化し、Vars_a 変数を allocate する。
  !
  subroutine dycore_dynamics_init( Dims, Vars_a )
  !==== Dependency
    use dycore_type_mod, only: DYCORE_VARS, DYCORE_DIMS, &
         &                     STRING, DBKIND, INTKIND
    use dycore_grid_mod, only: im, jm, km
    use dynamics_mod,    only: dynamics_init
    use spml_mod,        only: spml_init
    use dc_trace,        only: BeginSub, EndSub, DbgMessage
                                                                 !=end
    implicit none
                                                                 !=begin
    !==== Input
    !
    type(DYCORE_DIMS), intent(in) :: Dims   ! 次元データ全種
    !
    !==== Output
    !
    type(DYCORE_VARS), intent(out):: Vars_a ! 格子点データ全種(t+Δt)
                                                                 !=end

    !----- 作業用内部変数 -----
    character(STRING),  parameter:: subname = "dycore_dynamics_init"

  continue

    !----------------------------------------------------------------
    !   初期化確認
    !----------------------------------------------------------------
    call BeginSub(subname)
    if (dycore_dynamics_initialized) then
       call EndSub( subname, '%c is already called.', c1=trim(subname) )
       return
    else
       dycore_dynamics_initialized = .true.
    endif

    !----------------------------------------------------------------
    !   Version identifier
    !----------------------------------------------------------------
    call DbgMessage('%c :: %c', c1=trim(version), c2=trim(tagname))

    !-------------------------------------------------------------------
    !  SPMODEL 3次元モジュール初期化サブルーチン wa_initial
    !-------------------------------------------------------------------
    call spml_init

    !----------------------------------------------------------------
    !   Vars_a の各変数の allocate および初期化
    !----------------------------------------------------------------
    allocate( Vars_a%xyz_VelLon(im,jm,km) )
    allocate( Vars_a%xyz_VelLat(im,jm,km) )
    allocate( Vars_a%xyz_Vor(im,jm,km)  )
    allocate( Vars_a%xyz_Div(im,jm,km)  )
    allocate( Vars_a%xyz_Temp(im,jm,km) )
    allocate( Vars_a%xyz_QVap(im,jm,km) )
    allocate( Vars_a%xy_Ps(im,jm)       )

    Vars_a%xyz_VelLon = 0.0d0
    Vars_a%xyz_VelLat = 0.0d0
    Vars_a%xyz_Vor    = 0.0d0
    Vars_a%xyz_Div    = 0.0d0
    Vars_a%xyz_Temp   = 0.0d0
    Vars_a%xyz_QVap   = 0.0d0
    Vars_a%xy_Ps      = 0.0d0

    !----------------------------------------------------------------
    !   dynamics_init へ次元変数の引渡し
    !----------------------------------------------------------------
    call dynamics_init               &
         & ( Dims%x_Lon%a_Dim(:)   , & ! intent(in): 経度座標
         &   Dims%y_Lat%a_Dim(:)   , & ! intent(in): 緯度座標
         &   Dims%z_Sigma%a_Dim(:) , & ! intent(in): σレベル(整数)座標
         &   Dims%r_Sigma%a_Dim(:) ) ! intent(in): σレベル(半整数)座標

    call EndSub(subname)
  end subroutine dycore_dynamics_init




                                                                 !=begin
  !=== Calculate Predictional Values
  !
  !予報変数を計算し、Vars_a に返す。
  !
  subroutine dycore_dynamics_prediction( Dims, Vars_b, Vars_n, Vars_a )
  !==== Dependency
    use dycore_type_mod, only: DYCORE_VARS, DYCORE_DIMS, &
         &                     STRING, DBKIND, INTKIND
    use dynamics_mod,    only: dynamics_leapfrog
    use dc_trace,        only: BeginSub, EndSub, DbgMessage
                                                                 !=end
    implicit none
                                                                 !=begin
    !==== Input
    !
    type(DYCORE_DIMS), intent(in)   :: Dims   ! 次元データ全種
    type(DYCORE_VARS), intent(in)   :: Vars_b ! 格子点データ全種
    type(DYCORE_VARS), intent(in)   :: Vars_n ! 格子点データ全種
    !
    !==== Output
    !
    type(DYCORE_VARS), intent(inout):: Vars_a ! 格子点データ全種(t+Δt)
                                                                 !=end
    !----- 作業用内部変数 -----
    character(STRING),  parameter:: subname = "dycore_dynamics_prediction"

  continue

    !----------------------------------------------------------------
    !   初期化確認
    !----------------------------------------------------------------
    call BeginSub(subname)
    if (.not. dycore_dynamics_initialized) then
       call EndSub( subname, 'Call dycore_dynamics_init before call %c',  &
            &       c1=trim(subname) )
       return
    endif

    call dynamics_leapfrog            &
         & ( Dims%x_Lon%a_Dim(:)    , & ! intent(in): 経度座標
         &   Dims%y_Lat%a_Dim(:)    , & ! intent(in): 緯度座標
         &   Dims%z_Sigma%a_Dim(:)  , & ! intent(in): σレベル(整数)座標
         &   Dims%r_Sigma%a_Dim(:),& ! intent(in): σレベル(半整数)座標

         &   Vars_b%xyz_VelLon(:,:,:) , & ! intent(in): 速度経度成分 (t-Δt)
         &   Vars_b%xyz_VelLat(:,:,:) , & ! intent(in): 速度緯度成分 (t-Δt)
         &   Vars_b%xyz_Vor(:,:,:)    , & ! intent(in): 渦度         (t-Δt)
         &   Vars_b%xyz_Div(:,:,:)    , & ! intent(in): 発散         (t-Δt)
         &   Vars_b%xyz_Temp(:,:,:)   , & ! intent(in): 温度         (t-Δt)
         &   Vars_b%xyz_QVap(:,:,:)   , & ! intent(in): 比湿         (t-Δt)
         &   Vars_b%xy_Ps(:,:)        , & ! intent(in): 地表面気圧   (t-Δt)

         &   Vars_n%xyz_VelLon(:,:,:) , & ! intent(in): 速度経度成分 (t)
         &   Vars_n%xyz_VelLat(:,:,:) , & ! intent(in): 速度緯度成分 (t)
         &   Vars_n%xyz_Vor(:,:,:)    , & ! intent(in): 渦度         (t)
         &   Vars_n%xyz_Div(:,:,:)    , & ! intent(in): 発散         (t)
         &   Vars_n%xyz_Temp(:,:,:)   , & ! intent(in): 温度         (t)
         &   Vars_n%xyz_QVap(:,:,:)   , & ! intent(in): 比湿         (t)
         &   Vars_n%xy_Ps(:,:)        , & ! intent(in): 地表面気圧   (t)

         &   Vars_a%xyz_VelLon(:,:,:) , & ! intent(out): 速度経度成分 (t+Δt)
         &   Vars_a%xyz_VelLat(:,:,:) , & ! intent(out): 速度緯度成分 (t+Δt)
         &   Vars_a%xyz_Vor(:,:,:)    , & ! intent(out): 渦度         (t+Δt)
         &   Vars_a%xyz_Div(:,:,:)    , & ! intent(out): 発散         (t+Δt)
         &   Vars_a%xyz_Temp(:,:,:)   , & ! intent(out): 温度         (t+Δt)
         &   Vars_a%xyz_QVap(:,:,:)   , & ! intent(out): 比湿         (t+Δt)
         &   Vars_a%xy_Ps(:,:)      )     ! intent(out): 地表面気圧   (t+Δt)

    call EndSub(subname)
  end subroutine dycore_dynamics_prediction







                                                                 !=begin
  !=== Calculate Diagnostic Values
  !
  !渦度発散から、風速 (経度成分、緯度成分) を得る。
  !
  subroutine dycore_dynamics_diagnostic( Dims, Vars_a )
  !==== Dependency
    use dycore_type_mod, only: DYCORE_VARS, DYCORE_DIMS, &
         &                     STRING, DBKIND, INTKIND
    use dynamics_mod,    only: dynamics_diagnostic
    use dc_trace,        only: BeginSub, EndSub, DbgMessage
                                                                 !=end
    implicit none
                                                                 !=begin
    !==== Input
    !
    type(DYCORE_DIMS), intent(in)   :: Dims   ! 次元データ全種
    !
    !==== In/Out
    !
    type(DYCORE_VARS), intent(inout):: Vars_a ! 格子点データ全種(t+Δt)
                                                                 !=end
    !----- 作業用内部変数 -----
    character(STRING),  parameter:: subname = "dycore_dynamics_diagnostic"

  continue

    !-----------------------------------------------------------------
    !   初期化確認
    !-----------------------------------------------------------------
    call BeginSub(subname)
    if (.not. dycore_dynamics_initialized) then
       call EndSub( subname, 'Call dycore_dynamics_init before call %c',  &
            &       c1=trim(subname) )
       return
    endif

    call dynamics_diagnostic          &
         & ( Dims%x_Lon%a_Dim(:)    , & ! intent(in): 経度座標
         &   Dims%y_Lat%a_Dim(:)    , & ! intent(in): 緯度座標
         &   Dims%z_Sigma%a_Dim(:)  , & ! intent(in): σレベル(整数)座標
         &   Dims%r_Sigma%a_Dim(:),& ! intent(in): σレベル(半整数)座標

         &   Vars_a%xyz_VelLon(:,:,:) , & ! intent(out): 速度経度成分 (t+Δt)
         &   Vars_a%xyz_VelLat(:,:,:) , & ! intent(out): 速度緯度成分 (t+Δt)
         &   Vars_a%xyz_Vor(:,:,:)  , & ! intent(in) : 渦度         (t+Δt)
         &   Vars_a%xyz_Div(:,:,:)  , & ! intent(in) : 発散         (t+Δt)
         &   Vars_a%xyz_Temp(:,:,:) , & ! intent(in) : 温度         (t+Δt)
         &   Vars_a%xyz_QVap(:,:,:) , & ! intent(in) : 比湿         (t+Δt)
         &   Vars_a%xy_Ps(:,:)      )   ! intent(in) : 地表面気圧   (t+Δt)

    call EndSub(subname)
  end subroutine dycore_dynamics_diagnostic



                                                                 !=begin
  !=== Calculate Diffusion Terms
  !
  !水平拡散項の計算。
  !
  subroutine dycore_dynamics_diffusion( Vars_b, Vars_a )
  !==== Dependency
    use dycore_type_mod, only: DYCORE_VARS, DYCORE_DIMS, &
         &                     STRING, DBKIND, INTKIND
    use dynamics_mod,    only: dynamics_diffusion
    use dc_trace,        only: BeginSub, EndSub, DbgMessage
                                                                 !=end
    implicit none
                                                                 !=begin
    !==== Input
    !
    type(DYCORE_VARS), intent(in)   :: Vars_b ! 格子点データ全種(t-Δt)
    !
    !==== In/Out
    !
    type(DYCORE_VARS), intent(inout):: Vars_a ! 格子点データ全種(t+Δt)
                                                                 !=end
    !----- 作業用内部変数 -----
    character(STRING),  parameter:: subname = "dycore_dynamics_diffusion"

  continue

    !-----------------------------------------------------------------
    !   初期化確認
    !-----------------------------------------------------------------
    call BeginSub(subname)
    if (.not. dycore_dynamics_initialized) then
       call EndSub( subname, 'Call dycore_dynamics_init before call %c',  &
            &       c1=trim(subname) )
       return
    endif

    call dynamics_diffusion(   &
         & Vars_b%xyz_Vor    , & ! intent(in) : 渦度         (t-Δt)
         & Vars_b%xyz_Div    , & ! intent(in) : 発散         (t-Δt)
         & Vars_b%xyz_Temp   , & ! intent(in) : 温度         (t-Δt)
         & Vars_b%xyz_QVap   , & ! intent(in) : 比湿         (t-Δt)

         & Vars_a%xyz_Vor    , & ! intent(inout) : 渦度         (t+Δt)
         & Vars_a%xyz_Div    , & ! intent(inout) : 発散         (t+Δt)
         & Vars_a%xyz_Temp   , & ! intent(inout) : 温度         (t+Δt)
         & Vars_a%xyz_QVap   )   ! intent(inout) : 比湿         (t+Δt)

    call EndSub(subname)
  end subroutine dycore_dynamics_diffusion



                                                                 !=begin
  !=== Terminate module
  !
  !((< dynamics_mod >)) の終了処理を行なう。
  !
  subroutine dycore_dynamics_end
  !==== Dependency
    use dycore_type_mod, only: STRING, DBKIND, INTKIND
    use dynamics_mod,    only: dynamics_end
    use dc_trace,        only: BeginSub, EndSub, DbgMessage
                                                                 !=end
    implicit none

    !-----------------------------------------------------------------
    !   変数定義
    !-----------------------------------------------------------------
    !----- 作業用内部変数 -----
    character(STRING),  parameter:: subname = "dycore_dynamics_end"

  continue

    !-----------------------------------------------------------------
    !   初期化確認
    !-----------------------------------------------------------------
    call BeginSub(subname)
    if ( .not. dycore_dynamics_initialized) then
       call EndSub( subname, 'dycore_dynamics_init was not called', &
            &       c1=trim(subname) )
       return
    else
       dycore_dynamics_initialized = .false.
    endif

    call dynamics_end

    call EndSub(subname)
  end subroutine dycore_dynamics_end

end module dycore_dynamics_mod
