!---------------------------------------------------------------------
!     Copyright (C) GFD Dennou Club, 2006. All rights reserved.
!---------------------------------------------------------------------
!= Module MoistBuoy
!
!   * Developer: SUGIYAMA Ko-ichiro
!   * Version: $Id: $
!   * Tag Name: $Name:  $
!   * Change History: 
!
!== Overview
!
!
!== Error Handling
!
!== Bugs
!
!== Note
!
!
!== Future Plans
!
!

module MoistBuoy
  !
  !
  !

  !モジュール読み込み 
  use gridset, only:  SpcNum,            &! 化学種の数
    &                 DimXMin,           &! x 方向の配列の下限
    &                 DimXMax,           &! x 方向の配列の上限
    &                 DimZMin,           &! z 方向の配列の下限
    &                 DimZMax,           &! z 方向の配列の上限
    &                 DelX,              &! x 方向の格子点間隔
    &                 DelZ                ! z 方向の格子点間隔
  use basicset, only: CpDry,             &!乾燥成分の比熱
    &                 MolWtDry,          &!乾燥成分の分子量
    &                 Grav,              &!重力加速度
    &                 SpcWetID,          &!凝縮成分の ID
    &                 SpcWetSymbol,      &!凝縮成分の名前
    &                 MolWtWet,          &!凝縮成分の分子量
    &                 xz_PotTempBasicZ,  &!基本場の温位
    &                 xz_ExnerBasicZ,    &!エクスナー関数の基本場
    &                 xz_MixRtBasicZ      !基本場の混合比
  use ChemCalc, only: xz_LatentHeatPerMass       !潜熱
  use ChemData, only: ChemData_OneSpcID
  use average,  only: xr_avr_xz, xz_avr_xr
  use differentiate_center4, only: xr_dz_xz

  !暗黙の型宣言禁止
  implicit none
  
  !属性の指定
  private
  
  !関数を public に設定
  public MoistBuoy_Init
  public xz_MoistBuoyKm
  public xr_MoistBuoy

  !変数の定義
  integer     :: LoopNum      = 0
  integer     :: GasNum(10)   = 0
  integer     :: CloudNum(10) = 0
  real(8)     :: Cm           = 2.0d-1
  real(8)     :: MixLen       = 0.0d0
  
  save GasNum, CloudNum, LoopNum
  save Cm, MixLen

contains

!!!------------------------------------------------------------------!!!
  subroutine MoistBuoy_Init( )

    !暗黙の型宣言禁止
    implicit none

    !変数定義
    integer                  :: s
    integer                  :: n1

    !-----------------------------------------------------------
    ! 混合距離
    !-----------------------------------------------------------
    MixLen = sqrt(DelX * DelZ) 
    
    !-----------------------------------------------------------
    ! 雲粒と気体の ID の組を作る
    !-----------------------------------------------------------
    !化学種の中から雲粒を作るものを選び, その配列添え字と分子量を保管.
    LoopNum = 0
    SelectCloud: do s = 1, SpcNum
      
      ! NH4SH については無視
      if ( trim(SpcWetSymbol(s)) == 'NH4SH-s-Cloud' ) then 
        cycle SelectCloud
      end if

      !'Cloud' という文字列が含まれるものの個数を数える
      n1 = index(SpcWetSymbol(s), '-Cloud' )
      if (n1 /= 0) then
        LoopNum          = LoopNum + 1
        CloudNum(LoopNum)= s
        GasNum(LoopNum)  = minloc(SpcWetID, 1, SpcWetID == ChemData_OneSpcID(SpcWetSymbol(s)(1:n1-3) // '-g'))
      end if
    end do SelectCloud
    
    !-----------------------------------------------------------
    ! 確認
    !-----------------------------------------------------------
    write(*,*) "MoistAdjust_Init, LoopNum:  ", LoopNum
    write(*,*) "MoistAdjust_Init, CloudNum: ", CloudNum
    write(*,*) "MoistAdjust_Init, GasNum:   ", GasNum    

  end subroutine MoistBuoy_Init


!!!------------------------------------------------------------------!!!
  function xz_MoistBuoyKm(xz_Exner,  xz_PotTemp, xz_MixRt)
    !
    !乱流エネルギーの浮力項を計算
    !
    
    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(8), intent(in)  :: xz_Exner(DimXMin:DimXMax, DimZMin:DimZMax)
                                               !エクスナー関数の擾乱
    real(8), intent(in)  :: xz_PotTemp(DimXMin:DimXMax, DimZMin:DimZMax)
                                               !温位擾乱
    real(8), intent(in)  :: xz_MixRt(DimXMin:DimXMax, DimZMin:DimZMax, SpcNum)
                                               !凝縮成分の混合比
    real(8)              :: xz_MoistBuoyKm(DimXMin:DimXMax, DimZMin:DimZMax)
                                               !浮力項
    real(8)              :: xz_EquivPotTemp(DimXMin:DimXMax, DimZMin:DimZMax)
                                               !相当温位
    real(8)              :: xz_Temp(DimXMin:DimXMax, DimZMin:DimZMax)
                                               !温度
    real(8)              :: xz_LatentHeatPerMassAll(DimXMin:DimXMax, DimZMin:DimZMax, LoopNum)
                                               !潜熱の総和
    real(8)              :: xz_MixRtPerMolWt(DimXMin:DimXMax, DimZMin:DimZMax, LoopNum)
                                               !混合比 / 分子量
    real(8)              :: xz_MixRtBasicZPerMolWt(DimXMin:DimXMax, DimZMin:DimZMax, LoopNum)
                                               !基本場の混合比 / 分子量
    integer              :: s

    !初期化
    xz_Temp                = 0.0d0
    xz_LatentHeatPerMassAll       = 0.0d0
    xz_MixRtPerMolWt       = 0.0d0
    xz_MixRtBasicZPerMolWt = 0.0d0

    !作業配列の初期化. 気体のみ利用
    xz_Temp = (xz_Exner + xz_ExnerBasicZ) * (xz_PotTemp + xz_PotTempBasicZ)
    do s = 1, LoopNum
      xz_MixRtPerMolWt(:,:,GasNum(s)) = xz_MixRt(:,:,GasNum(s)) / MolWtWet(GasNum(s))

      xz_MixRtBasicZPerMolWt(:,:,GasNum(s)) = &
        & xz_MixRtBasicZ(:,:,GasNum(s)) / MolWtWet(GasNum(s))

      xz_LatentHeatPerMassAll(:,:,GasNum(s)) = &
        &  (xz_MixRt(:,:,GasNum(s)) + xz_MixRtBasicZ(:,:,GasNum(s))) &
        &   * xz_LatentHeatPerMass(SpcWetID(CloudNum(s)), xz_Temp)
    end do
  
    !相当温位の計算
    xz_EquivPotTemp = 0.0d0 
    xz_EquivPotTemp =                                           & 
      &   sum(xz_LatentHeatPerMassAll, 3) / (CpDry * xz_ExnerBasicZ)   &
      & + xz_PotTempBasicZ                                      &
      &   * (                                                   &
      &       + sum(xz_MixRtPerMolWt, 3)                        &
      &           / ( +  1.0d0 / MolWtDry                       &
      &               + sum(xz_MixRtBasicZPerMolWt, 3) )        &
      &       - sum(xz_MixRt, 3)                                &
      &          / ( 1.0d0 + sum(xz_MixRtBasicZ, 3))            &
      &      )
    
    !浮力項の計算
    xz_MoistBuoyKm = 0.0d0
    xz_MoistBuoyKm = &
      &  - 3.0d0 * Grav * ( Cm ** 2.0d0 ) * ( MixLen ** 2.0d0 ) &
      &       * xz_avr_xr( xr_dz_xz( xz_EquivPotTemp ) ) &
      &       / ( 2.0d0 * xz_PotTempBasicZ )
    
  end function xz_MoistBuoyKm
  

!!!------------------------------------------------------------------------!!!
  function xr_MoistBuoy(xz_MixRt)
    !
    ! 鉛直方向の運動方程式に現れる浮力項のうち, 
    ! 分子量の効果だけを求める
    !
    
    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(8), intent(in)  :: xz_MixRt(DimXMin:DimXMax, DimZMin:DimZMax, SpcNum)
                                               !凝縮成分の混合比
    real(8)              :: xr_MoistBuoy(DimXMin:DimXMax, DimZMin:DimZMax)
                                               !浮力項(分子量効果)
    real(8)              :: xz_MixRtPerMolWt(DimXMin:DimXMax, DimZMin:DimZMax, LoopNum)
                                               !混合比 / 分子量
    real(8)              :: xz_MixRtBasicZPerMolWt(DimXMin:DimXMax, DimZMin:DimZMax, LoopNum)
                                               !基本場の混合比 / 分子量
    integer              :: s
    
    !初期化
    xr_MoistBuoy           = 0.0d0
    xz_MixRtPerMolWt       = 0.0d0
    xz_MixRtBasicZPerMolWt = 0.0d0

    !作業配列の初期化. 気体のみ利用
    do s = 1, LoopNum
      xz_MixRtPerMolWt(:,:,GasNum(s)) = xz_MixRt(:,:,GasNum(s)) / MolWtWet(GasNum(s))

      xz_MixRtBasicZPerMolWt(:,:,GasNum(s)) = &
        & xz_MixRtBasicZ(:,:,GasNum(s)) / MolWtWet(GasNum(s))
    end do
    
    !浮力項の計算
    xr_MoistBuoy =                                            &
      & + Grav * xr_avr_xz( sum(xz_MixRtPerMolWt, 3) )        &
      &    / ( +  1.0d0 / MolWtDry                            &
      &        + xr_avr_xz( sum(xz_MixRtBasicZPerMolWt, 3) )) &
      & - Grav * xr_avr_xz( sum(xz_MixRt, 3) )                &
      &    / ( + 1.0d0 + xr_avr_xz( sum(xz_MixRtBasicZ, 3) ) )
    
  end function xr_MoistBuoy

  
end module MoistBuoy
