!---------------------------------------------------------------------
!     Copyright (C) GFD Dennou Club, 2005. All rights reserved.
!---------------------------------------------------------------------
! physics_verdiff_main.f90 
!
! History
!   2005/09/21 Yamada Yukiko     create
!

module physics_verdiff_main_mod

  implicit none

  private
  public :: physics_verdiff_main

contains

  subroutine physics_verdiff_main( &
         & xyr_VelLonFlux       , & ! (out) 速度経度成分フラックス
         & xyr_VelLatFlux       , & ! (out) 速度緯度成分フラックス
         & xyr_TempFlux         , & ! (out) 温度フラックス
         & xyr_QvapFlux         , & ! (out) 比湿フラックス
         & xyzo_VelMatrix       , & ! (inout) 速度陰解行列
         & xyzo_TempMatrix      , & ! (inout) 温度陰解行列
         & xyzo_QvapMatrix      , & ! (inout) 比湿陰解行列
         & xyz_VelLon           , & ! (in) 速度経度成分
         & xyz_VelLat           , & ! (in) 速度緯度成分
         & xyz_Temp             , & ! (in) 温度 (整数)
         & xyr_Temp             , & ! (in) 温度 (半整数)
         & xyz_Qvap             , & ! (in) 比湿 (整数)
         & xyz_Press            , & ! (in) 気圧 (整数)
         & xyr_Press            , & ! (in) 気圧 (半整数)
         & xyz_GeoPot           , & ! (in) 高度 (整数)
         & xyr_GeoPot             ) ! (in) 高度 (半整数)

    !==== Dependency
    use type_mod,    only: REKIND, DBKIND, INTKIND, TOKEN, STRING
    use grid_3d_mod, only: im, jm, km
    use constants_mod, only: RAir, Cp, Grav, EL
    use physics_verdiff_coeff_mod,  only: physics_verdiff_coeff
    use dc_trace,    only: SetDebug, BeginSub, EndSub, DbgMessage, DataDump

    implicit none

    !==== Output
    !
    real(DBKIND), intent(out) :: &
         & xyr_VelLonFlux(im,jm,km+1)        , & ! (out) 速度経度成分フラックス
         & xyr_VelLatFlux(im,jm,km+1)        , & ! (out) 速度緯度成分フラックス
         & xyr_TempFlux(im,jm,km+1)          , & ! (out) 温度フラックス
         & xyr_QvapFlux(im,jm,km+1)              ! (out) 比湿フラックス

    !==== Input
    !
    real(DBKIND), intent(in) :: &
         & xyz_VelLon(im,jm,km)              , & ! (in) 速度経度成分
         & xyz_VelLat(im,jm,km)              , & ! (in) 速度緯度成分
         & xyz_Temp(im,jm,km)                , & ! (in) 温度 (整数)
         & xyr_Temp(im,jm,km+1)              , & ! (in) 温度 (半整数)
         & xyz_Qvap(im,jm,km)                , & ! (in) 比湿 (整数)
         & xyz_Press(im,jm,km)               , & ! (in) 気圧 (整数)
         & xyr_Press(im,jm,km+1)             , & ! (in) 気圧 (半整数)
         & xyz_GeoPot(im,jm,km)              , & ! (in) 高度 (整数)
         & xyr_GeoPot(im,jm,km+1)                ! (in) 高度 (半整数)

    !==== In/Out
    !
    real(DBKIND), intent(inout) :: &
         & xyzo_VelMatrix(im,jm,km,-1:1)    , & ! (inout) 速度陰解行列
         & xyzo_TempMatrix(im,jm,0:km,-1:1) , & ! (inout) 温度陰解行列
         & xyzo_QvapMatrix(im,jm,km,-1:1)       ! (inout) 比湿陰解行列

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

    ! do ループ用作業変数 (東西 i*、南北 j*、鉛直 k*、波数 l*用)
    integer(INTKIND)    :: i,j, k

    real(DBKIND), parameter :: RefPress        = 100000.0D0 ! 参照気圧
    real(DBKIND), parameter :: BasePotTemp     = 300.0D0    ! 基本温位
    real(DBKIND), parameter :: SquareVelMin    = 0.1D0      ! 風二乗差最小値
    real(DBKIND), parameter :: BulkRiNumMin    = - 100.0D0  ! バルクＲｉ数最小値

    real(DBKIND) :: &
         & xyr_DVelDz(im,jm,km+1)            , & ! d|v|/dz
         & xyr_BulkRiNum(im,jm,km+1)         , & ! バルクＲｉ数
         & xyr_TempTransCoeff(im,jm,km+1)    , & ! 輸送係数：温度
         & xyr_QvapTransCoeff(im,jm,km+1)    , & ! 輸送係数：比湿
         & xyr_VelTransCoeff(im,jm,km+1)     , & ! 輸送係数：運動量
         & xyr_TempDiffuCoeff(im,jm,km+1)    , & ! 拡散係数：温度
         & xyr_QvapDiffuCoeff(im,jm,km+1)    , & ! 拡散係数：比湿
         & xyr_VelDiffuCoeff(im,jm,km+1)     , & ! 拡散係数：運動量
         & xyz_Exner(im,jm,km)               , & ! Exner関数 (整数)
         & xyr_Exner(im,jm,km+1)                 ! Exner関数 (半整数)

    continue

    !----------------------------------------------------------------
    !   開始処理
    !----------------------------------------------------------------
    call BeginSub(subname)

    !----------------------------------------------------------------
    !   鉛直拡散計算
    !----------------------------------------------------------------

    ! ---- 1. 定数計算 ----
    xyz_Exner = ( xyz_Press / RefPress ) ** (RAir/Cp)
    xyr_Exner = ( xyr_Press / RefPress ) ** (RAir/Cp)

    ! ---- 2. バルクＲｉ数 ----

    xyr_DVelDz    = 0.0d0
    xyr_BulkRiNum = 0.0d0

    do k = 2, km 
       do i = 1, im
          do j = 1, jm
             xyr_DVelDz(i,j,k) = &
                  &  SQRT( MAX( SquareVelMin , &
                  &            ( xyz_VelLon(i,j,k) - xyz_VelLon(i,j,k-1) )**2 & 
                  &          + ( xyz_VelLat(i,j,k) - xyz_VelLat(i,j,k-1) )**2 &
                  &       )    ) &
                  &  / ( xyz_GeoPot(i,j,k) - xyz_GeoPot(i,j,k-1) )

             xyr_BulkRiNum(i,j,k) = &
                  &  Grav / BasePotTemp &
                  &  *  (   xyz_Temp(i,j,k)   / xyz_Exner(i,j,k)     &
                  &       - xyz_Temp(i,j,k-1) / xyz_Exner(i,j,k-1) ) &
                  &  / ( xyz_GeoPot(i,j,k) - xyz_GeoPot(i,j,k-1) )   &
                  &  / xyr_DVelDz(i,j,k)**2

             xyr_BulkRiNum(i,j,k) = MAX( xyr_BulkRiNum(i,j,k) , BulkRiNumMin )

          end do
       end do
    end do

    ! ---- 3. 拡散係数 ----    

    call physics_verdiff_coeff( &
       & xyr_VelDiffuCoeff , & ! (out) 
       & xyr_TempDiffuCoeff, & ! (out) 
       & xyr_QvapDiffuCoeff, & ! (out) 
       & xyr_BulkRiNum     , & ! (in) 
       & xyr_DVelDz        , & ! (in) 
       & xyr_GeoPot )          ! (in) 

    ! ----  *. 浅い積雲対流 ----
    
    ! ----  *. 拡散係数の出力 ----
    
!    CALL HISTIN ( DFM  , 'DFM'  )
!    CALL HISTIN ( DFH  , 'DFH'  )
!    CALL HISTIN ( DFE  , 'DFE'  )

   ! ----  5. 輸送係数 ----
    
    xyr_VelTransCoeff  = 0.0d0
    xyr_TempTransCoeff = 0.0d0
    xyr_QvapTransCoeff = 0.0d0

    do k = 2, km
       xyr_VelTransCoeff(:,:,k) = xyr_VelDiffuCoeff(:,:,k) &
            &                       * xyr_Press(:,:,k) / RAir / xyr_Temp(:,:,k) &
            &                       / ( xyz_GeoPot(:,:,k) - xyz_GeoPot(:,:,k-1) )
       xyr_TempTransCoeff(:,:,k) = xyr_TempDiffuCoeff(:,:,k) &
            &                       * xyr_Press(:,:,k) / RAir / xyr_Temp(:,:,k) &
            &                       / ( xyz_GeoPot(:,:,k) - xyz_GeoPot(:,:,k-1) )
       xyr_QvapTransCoeff(:,:,k) = xyr_QvapDiffuCoeff(:,:,k) &
            &                       * xyr_Press(:,:,k) / RAir / xyr_Temp(:,:,k) &
            &                       / ( xyz_GeoPot(:,:,k) - xyz_GeoPot(:,:,k-1) )
    end do

   ! ----  5. フラックス----

    ! k =0, km+1 も 0 でいいのかな. 
    xyr_VelLonFlux  = 0.0d0
    xyr_VelLatFlux  = 0.0d0
    xyr_TempFlux    = 0.0d0
    xyr_QvapFlux    = 0.0d0

    do k = 2, km

       xyr_VelLonFlux(:,:,k) = xyr_VelLonFlux(:,:,k) &
            &                 + xyr_VelTransCoeff(:,:,k) &
            &                   * ( xyz_VelLon(:,:,k-1) - xyz_VelLon(:,:,k) )


       xyr_VelLatFlux(:,:,k) = xyr_VelLatFlux(:,:,k) &
            &                 + xyr_VelTransCoeff(:,:,k) &
            &                   * ( xyz_VelLat(:,:,k-1) - xyz_VelLat(:,:,k) )

       xyr_TempFlux(:,:,k) = xyr_TempFlux(:,:,k) &
            &               + Cp * xyr_TempTransCoeff(:,:,k) * xyr_Exner(:,:,k) &
            &                * (   xyz_Temp(:,:,k-1) / xyz_Exner(:,:,k-1) &
            &                    - xyz_Temp(:,:,k)   / xyz_Exner(:,:,k)  )

       xyr_QvapFlux(:,:,k) = xyr_QvapFlux(:,:,k) &
            &                 + EL * xyr_QvapTransCoeff(:,:,k) &
            &                   * ( xyz_Qvap(:,:,k-1) - xyz_Qvap(:,:,k) )

    end do

   ! ----  5. 陰解用行列 ----

    do k = 2, km 
       xyzo_VelMatrix(:,:,k,0)  = xyzo_VelMatrix(:,:,k,0) + xyr_VelTransCoeff(:,:,k)
       xyzo_VelMatrix(:,:,k,-1) =                         - xyr_VelTransCoeff(:,:,k)

       xyzo_TempMatrix(:,:,k,0)  = xyzo_TempMatrix(:,:,k,0) &
            &                      + Cp * xyr_TempTransCoeff(:,:,k) &
            &                        * xyr_Exner(:,:,k) / xyz_Exner(:,:,k) 
       xyzo_TempMatrix(:,:,k,-1) = - Cp * xyr_TempTransCoeff(:,:,k) &
            &                        * xyr_Exner(:,:,k) / xyz_Exner(:,:,k-1) 

       xyzo_QvapMatrix(:,:,k,0)  = xyzo_QvapMatrix(:,:,k,0) &
            &                      + Cp * xyr_QvapTransCoeff(:,:,k)
       xyzo_QvapMatrix(:,:,k,-1) = - Cp * xyr_QvapTransCoeff(:,:,k) 
    end do

    do k = 1, km-1
       xyzo_VelMatrix(:,:,k,0)  = xyzo_VelMatrix(:,:,k,0) & 
            &                     + xyr_VelTransCoeff(:,:,k+1)
       xyzo_VelMatrix(:,:,k,1)  = - xyr_VelTransCoeff(:,:,k+1) 

       xyzo_TempMatrix(:,:,k,0)  = xyzo_TempMatrix(:,:,k,0) &
            &                       + Cp * xyr_TempTransCoeff(:,:,k+1) &
            &                        * xyr_Exner(:,:,k+1) / xyz_Exner(:,:,k) 
       xyzo_TempMatrix(:,:,k,1)  = - Cp * xyr_TempTransCoeff(:,:,k+1) &
            &                        * xyr_Exner(:,:,k+1) / xyz_Exner(:,:,k+1) 

       xyzo_QvapMatrix(:,:,k,0)  = xyzo_QvapMatrix(:,:,k,0) &
            &                      + Cp * xyr_QvapTransCoeff(:,:,k+1)
       xyzo_QvapMatrix(:,:,k,1)  = - Cp * xyr_QvapTransCoeff(:,:,k+1) 
    end do

    !----------------------------------------------------------------
    !   終了処理
    !----------------------------------------------------------------
    call EndSub(subname)

  end subroutine physics_verdiff_main


end module physics_verdiff_main_mod
















