!= Module Dynamical_PotTemp
!
! Authors::   SUGIYAMA Ko-ichiro, ODAKA Masatsugu 
! Version::   $Id: dynamic_pottemp.f90,v 1.1 2011-04-26 04:08:10 sugiyama Exp $ 
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2007. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!
!== Overview 
!
!モデルの力学過程を計算するために必要となる関数群を束ねたモジュール
!具体的には以下の項を計算するための関数を格納する.  
!  * 移流項
!  * 浮力項
!  * 気圧傾度力項
!
!== Error Handling
!
!== Known Bugs
!
!== Note
!
!  * エクスナー関数の空間方向の離散化において, 2 次精度の離散化を陽に利用しているため, 気圧傾度力項の計算プログラムにおいて differentiate_center4 モジュールを指定することはできないので注意.
!
!== Future Plans
!

module Dynamic_PotTemp
  !
  !陽開放を用いた力学過程の各項の計算モジュール. 
  !具体的には以下の項を計算するための関数を格納する.  
  !  * 移流項
  !  * 浮力項
  !  * 気圧傾度力項
  !

  !モジュール読み込み
  use dc_types, only: DP

  use gridset, only:  imin,           &! x 方向の配列の下限
    &                 imax,           &! x 方向の配列の上限
    &                 jmin,           &! y 方向の配列の下限
    &                 jmax,           &! y 方向の配列の上限
    &                 kmin,           &! z 方向の配列の下限
    &                 kmax,           &! z 方向の配列の上限
    &                 nx,ny,nz,nf      !
  use basicset, only: xyz_PotTempBasicZ   !基本場の温位
  use constants,only: CpDry,             &!乾燥成分の比熱
    &                 Grav,              &!重力加速度
    &                 NuV, NuH,          &!数値拡散
    &                 Nu                  !音波の減衰係数
  use axesset, only: &
    &                xyz_avr_pyz, xyr_avr_pyr, xqz_avr_pqz, &
    &                pyz_avr_xyz, pyr_avr_xyr, pqz_avr_xqz, &
    &                xyz_avr_xqz, pyz_avr_pqz, xyr_avr_xqr, &
    &                xqz_avr_xyz, pqz_avr_pyz, xqr_avr_xyr, &
    &                xyz_avr_xyr, pyz_avr_pyr, xqz_avr_xqr, &
    &                xyr_avr_xyz, pyr_avr_pyz, xqr_avr_xqz 

  !暗黙の型宣言禁止
  implicit none

  !属性の指定
  private

  !移流項計算のための関数を public にする
  public dynamic_pottemp_init
  public tendency_dynamic_pottemp

contains

  subroutine dynamic_pottemp_init()

    implicit none

    call dynamic_pottemp_historyadd()


  end subroutine dynamic_pottemp_init


  subroutine dynamic_pottemp_historyadd

    use gtool_historyauto, only: HistoryAutoAddVariable

    implicit none

    call HistoryAutoAddVariable(  &
      & varname='PotTempAdv', &
      & dims=(/'x','y','z','t'/),     &
      & longname='Advection term of potential temperature',  &
      & units='K.s-1',    &
      & xtype='double')


    call HistoryAutoAddVariable(  &
      & varname='PotTempDiff', &
      & dims=(/'x','y','z','t'/),     &
      & longname='Numerical Diffusion term of potential temperature', &
      & units='K.s-1"',    &
      & xtype='double')
    
  end subroutine Dynamic_pottemp_historyadd


  subroutine Tendency_Dynamic_PotTemp(  &
    & Time, pyz_VelXNl, xqz_VelYNl, xyr_VelZNl, xyz_PotTempBl, xyz_PotTempNl,xyz_Dyn)
    ! 温位の移流拡散の計算 
    ! Advection and diffusion of potential temperature.
    !

    implicit none

    real(DP), intent(in)  :: Time
    real(DP), intent(in)  :: pyz_VelXNl(imin:imax, jmin:jmax, kmin:kmax)
    real(DP), intent(in)  :: xqz_VelYNl(imin:imax, jmin:jmax, kmin:kmax)
    real(DP), intent(in)  :: xyr_VelZNl(imin:imax, jmin:jmax, kmin:kmax)
    real(DP), intent(in)  :: xyz_PotTempBl(imin:imax, jmin:jmax, kmin:kmax)
    real(DP), intent(in)  :: xyz_PotTempNl(imin:imax, jmin:jmax, kmin:kmax)
    real(DP), intent(out) :: xyz_Dyn(imin:imax, jmin:jmax, kmin:kmax)

    real(DP) :: xyz_Adv(imin:imax, jmin:jmax, kmin:kmax)
    real(DP) :: xyz_Diff(imin:imax, jmin:jmax, kmin:kmax)
     
    xyz_Adv  = xyz_AdvScalar(                                                          &
      &          xyz_PotTempNl + xyz_PotTempBasicZ, pyz_VelXNl, xqz_VelYNl, xyr_VelZNl &
      &        )
!    xyz_Turb = xyz_TurbScalar(xyz_PotTempBl + xyz_PotTempBasicZ, xyz_KhBl)
    xyz_Diff = xyz_NumDiffScalar(xyz_PotTempBl)
    
    xyz_Dyn = xyz_Adv + xyz_Diff     
    
    ! Output
    !     
    call HistoryAutoPut(Time, 'PotTempAdv',  xyz_Adv(1:nx, 1:ny, 1:nz))
    call HistoryAutoPut(Time, 'PotTempDiff', xyz_Diff(1:nx, 1:ny, 1:nz))

  end subroutine Tendency_Dynamic_PotTemp


!!!------------------------------------------------------------------------!!!
  function xyz_AdvScalar(xyz_Var, pyz_VelX, xqz_VelY, xyr_VelZ)
    !
    ! x, z 方向に半格子ずれた点における移流を計算
    !
    
    !モジュール読み込み
    use xyz_deriv_c4_module, only: pyz_dx_xyz, xqz_dy_xyz, xyr_dz_xyz

    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(DP), intent(in) :: pyz_VelX &
      &                    (imin:imax,jmin:jmax,kmin:kmax)
                                                        !水平風速
    real(DP), intent(in) :: xqz_VelY &
      &                    (imin:imax,jmin:jmax,kmin:kmax)
                                                        !水平風速
    real(DP), intent(in) :: xyr_VelZ &
      &                    (imin:imax,jmin:jmax,kmin:kmax)
                                                        !鉛直風速
    real(DP), intent(in) :: xyz_Var &
      &                    (imin:imax,jmin:jmax,kmin:kmax)
                                                        !スカラー量
    real(DP)             :: xyz_AdvScalar &
      &                    (imin:imax,jmin:jmax,kmin:kmax)
                                                        !スカラー量の水平移流
    
    xyz_AdvScalar =                               &
      & - xyz_avr_pyz(pyz_VelX * pyz_dx_xyz(xyz_Var))  &
      & - xyz_avr_xqz(xqz_VelY * xqz_dy_xyz(xyz_Var))  &
      & - xyz_avr_xyr(xyr_VelZ * xyr_dz_xyz(xyz_Var))    

  end function xyz_AdvScalar


!!!-------------------------------------------------------------------!!!
  function xyz_NumDiffScalar(xyz_Scalar)
    !
    ! x, y, z 方向に半格子ずれた点での数値拡散項を評価
    !
    
    !モジュール読み込み
    use xyz_deriv_module, only: pyz_dx_xyz, xyz_dy_xqz, xqz_dy_xyz, xyz_dz_xyr, xyr_dz_xyz, xyz_dx_pyz

    !暗黙の型宣言禁止
    implicit none

    !変数定義
    real(DP), intent(in) :: xyz_Scalar &
      &                     (imin:imax,jmin:jmax,kmin:kmax)
                                                    !スカラー量
    real(DP)             :: xyz_NumDiffScalar &
      &                     (imin:imax,jmin:jmax,kmin:kmax)
                                                    !水平方向の数値拡散
    
    xyz_NumDiffScalar =   &
      &    NuH * (xyz_dx_pyz(pyz_dx_xyz( xyz_Scalar ))) &
      &  + NuH * (xyz_dy_xqz(xqz_dy_xyz( xyz_Scalar ))) &
      &  + NuV * (xyz_dz_xyr(xyr_dz_xyz( xyz_Scalar ))) 
    
  end function xyz_NumDiffScalar

end module Dynamic_PotTemp
