!= Module BasicSet
!
! Authors::   SUGIYAMA Ko-ichiro, ODAKA Masatsugu
! Version::   $Id: basicset.f90,v 1.16 2010-08-13 07:18:16 sugiyama Exp $
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2006. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!
!== Overview 
!
! デフォルトの基本場を設定するための変数参照型モジュール
! * BasicEnvFile_init: 基本場の値を netCDF ファイルから取得
! * BasicEnvCalc_Init: 基本場の情報を Namelist から取得して値を計算
!
!== Error Handling
!
!== Known Bugs
!
!== Note
!
!== Future Plans
!

module BasicSet
  !
  !デフォルトの基本場を設定するための変数参照型モジュール
  !ただし, hogeBasicZ となる配列は, 外部から値を入力することで
  !初期化を行う. 
  !

  !モジュール読み込み
  use dc_message, only: MessageNotify          !メッセージ出力
  use DebugSet,   only: cpurank
  use ChemData,   only: GasRUniv,             &!普遍気体定数
    &                   ChemData_OneSpcID,    &!化学種の ID
    &                   ChemData_CpPerMolRef, &!標準状態での比熱
    &                   ChemData_MolWt         !分子量
  use gridset,    only: DimXMin,       &! 配列の X 方向の下限
    &                   DimXMax,       &! 配列の X 方向の上限
    &                   DimZMin,       &! 配列の Z 方向の下限
    &                   DimZMax,       &! 配列の Z 方向の上限
    &                   SpcNum          ! 化学種の数

  !暗黙の型宣言禁止
  implicit none

  !save 属性
  save

  !Public Interface
  real(8)               :: Grav                  !重力 [m/s^2]
  real(8)               :: TempSfc               !地表面温度 [K]
  real(8)               :: PressSfc              !地表面圧力 [Pa]
  real(8)               :: PressBasis            !温位の基準圧力 [Pa]
  real(8)               :: CpDry                 !乾燥成分の定圧比熱 [J/K kg]
  real(8)               :: CpDryMol              !乾燥成分の定圧比熱 [J/K kg]
  real(8)               :: CvDry                 !乾燥成分の定積比熱 [J/K kg]
  real(8)               :: MolWtDry              !乾燥成分の分子量   [kg/mol]
  real(8)               :: GasRDry               !乾燥成分の気体定数 [J/K kg]
  integer, allocatable  :: SpcWetID(:)           !湿潤成分の化学種のID
  real(8), allocatable  :: MolWtWet(:)           !湿潤成分の分子量  
  real(8), allocatable  :: xz_DensBasicZ(:,:)    !密度
  real(8), allocatable  :: xz_PressBasicZ(:,:)   !無次元圧力
  real(8), allocatable  :: xz_ExnerBasicZ(:,:)   !無次元圧力
  real(8), allocatable  :: xz_TempBasicZ(:,:)    !温度
  real(8), allocatable  :: xz_PotTempBasicZ(:,:) !温位
  real(8), allocatable  :: xz_VelSoundBasicZ(:,:)!音速
  real(8), allocatable  :: xza_MixRtBasicZ(:,:,:)!凝縮成分混合比
  real(8), allocatable  :: xz_EffMolWtBasicZ(:,:)!分子量効果
  real(8)               :: SpcWetMolFr(10)       !湿潤成分の化学種の存在度
  character(20)         :: SpcWetSymbol(10)      !湿潤成分の化学種名
  real(8)               :: Tropopause            !対流圏圏界面高度
  real(8)               :: Humidity              !相対湿度 
  character(20)         :: EnvType               !基本場の温度設定, 'Dry' or 'Moist'   
  real(8)               :: TempStrat             !成層圏の温度 [k]
  real(8)               :: Dhight                !重み関数のパラメータ [m]


contains

!!!-----------------------------------------------------------------!!!
  subroutine BasicSetArray_Init(                         &
    & xz_Press, xz_Exner, xz_Temp, xz_PotTemp, xz_Dens,  &
    & xz_VelSound, xza_MixRt, xz_EffMolWt )
    !
    !基本場の値を外部から取得する. 
    !
    
    !入力変数
    real(8), intent(in) :: xz_Press(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8), intent(in) :: xz_Exner(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8), intent(in) :: xz_Temp(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8), intent(in) :: xz_PotTemp(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8), intent(in) :: xz_Dens(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8), intent(in) :: xz_VelSound(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8), intent(in) :: xza_MixRt(DimXMin:DimXMax, DimZMin:DimZMax, SpcNum)
    real(8), intent(in) :: xz_EffMolWt(DimXMin:DimXMax, DimZMin:DimZMax)
   
    !---------------------------------------------------------------
    ! *BasicZ な配列の初期化
    !---------------------------------------------------------------
    !配列の割り当て
    allocate( & 
      & xz_DensBasicZ(DimXMin:DimXMax, DimZMin:DimZMax),            &
      & xz_PressBasicZ(DimXMin:DimXMax, DimZMin:DimZMax),           &
      & xz_ExnerBasicZ(DimXMin:DimXMax, DimZMin:DimZMax),           &
      & xz_TempBasicZ(DimXMin:DimXMax, DimZMin:DimZMax),            &
      & xz_PotTempBasicZ(DimXMin:DimXMax, DimZMin:DimZMax),         &
      & xz_VelSoundBasicZ(DimXMin:DimXMax, DimZMin:DimZMax),        &
      & xza_MixRtBasicZ(DimXMin:DimXMax, DimZMin:DimZMax, SpcNum),   &
      & xz_EffMolWtBasicZ(DimXMin:DimXMax, DimZMin:DimZMax)         )
    
    !値の入力
    xz_PressBasicZ    = xz_Press
    xz_ExnerBasicZ    = xz_Exner
    xz_TempBasicZ     = xz_Temp
    xz_PotTempBasicZ  = xz_PotTemp
    xz_DensBasicZ     = xz_Dens
    xz_VelSoundBasicZ = xz_VelSound
    xza_MixRtBasicZ   = xza_MixRt
    xz_EffMolWtBasicZ = xz_EffMolWt
    
  end subroutine BasicSetArray_Init

!!!-----------------------------------------------------------------!!!
  subroutine BasicSet_Init(cfgfile)
    !
    !基本場の情報を Namelist から取得して値を計算
    !

    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    character(*), intent(in)   :: cfgfile         !NAMELIST ファイル
!    real(8)                   :: Tropopause      !対流圏圏界面高度
!    real(8)                   :: CpDryMol        !乾燥成分の定圧比熱 [J/K mol]
    integer                    :: SpcDryNum       !乾燥成分の化学種の数
    integer                    :: SpcWetNum       !湿潤成分の化学種の数
    character(20)              :: SpcDrySymbol(5)!乾燥成分の化学種名
!    character(15)             :: SpcWetSymbol(10)!湿潤成分の化学種名
    real(8)                    :: SpcDryMolFr(5) !乾燥成分の化学種の存在度
!    real(8)                   :: SpcWetMolFr(10) !湿潤成分の化学種の存在度
    integer, allocatable       :: SpcDryID(:)     !乾燥成分の化学種のID
!    real(8)                   :: Humidity        !相対湿度
!    character(20)             :: EnvType         !基本場の温度設定, 'Dry' or 'Moist'
    real(8), allocatable       :: PropertyDry(:)  !作業配列
    character(20), allocatable :: Symbol(:)       !作業配列
    integer                    :: s, n1, n2, n3   !作業変数    

    !NAMELIST の定義
    NAMELIST /basicset/ &
      & Grav, TempSfc, PressSfc,   PressBasis, Tropopause,  & 
      & SpcDrySymbol, SpcDryMolFr,                          &
      & SpcWetSymbol, SpcWetMolFr,                          &
      & EnvType, Humidity, TempStrat, Dhight

    SpcDrySymbol = '' 
    SpcDryMolFr  = 0.0d0
    SpcWetSymbol = '' 
    SpcWetMolFr  = 0.0d0
    
    !ファイルオープン. 情報取得. 
    open (10, FILE=cfgfile)
    read(10, NML=basicset)
    close(10)

    !----------------------------------------------------------
    ! 乾燥成分の物性値の初期化
    !----------------------------------------------------------
    !乾燥成分の個数を数える
    SpcDryNum = count(SpcDrySymbol /= "")
    
    !化学種の ID を取得    
    allocate(SpcDryID(SpcDryNum))    
    do s = 1, SpcDryNum
      SpcDryID(s) = ChemData_OneSpcID( SpcDrySymbol(s) )
    end do

    !作業配列の準備
    allocate(PropertyDry(SpcDryNum))

    !分子量
    do s = 1, SpcDryNum
      PropertyDry(s) = ChemData_MolWt(SpcDryID(s))
    end do
    MolWtDry = dot_product(PropertyDry, SpcDryMolFr(1:SpcDryNum)) 
    
    !定圧比熱(モル当量)
    do s = 1, SpcDryNum    
      PropertyDry(s) = ChemData_CpPerMolRef(SpcDryID(s))
    end do
    CpDryMol = dot_product(PropertyDry, SpcDryMolFr(1:SpcDryNum)) 
    
    !定圧比熱
    CpDry    = CpDryMol / MolWtDry
    
    !気体定数
    GasRDry = GasRUniv / MolWtDry
    
    !定積比熱
    CvDry    = CpDry - GasRDry
    
    
    !----------------------------------------------------------
    ! 湿潤成分の ID を得る
    !----------------------------------------------------------
    !湿潤成分の個数を数える
    SpcWetNum = count(SpcWetSymbol /= "")
    if (SpcWetNum /= SpcNum) then 
      call MessageNotify( "E", &
        &  "basicset: ", "SpcWetNum is not equal to SpcNum." )
    end if
    
    !配列の割り当て
    allocate(SpcWetID(SpcWetNum), Symbol(SpcWetNum), MolWtWet(SpcWetNum))

    !SpcWetSymbol の文字列から, -Rain, -Cloud を除いたものを Symbol として保管
    do s = 1, SpcWetNum
      n1 = index(SpcWetSymbol(s), '-Cloud' )
      n2 = index(SpcWetSymbol(s), '-Rain' )
      n3 = max(n1, n2)
      if (n3 == 0) then
        Symbol(s) = SpcWetSymbol(s)
      else
        Symbol(s) = SpcWetSymbol(s)(1:n3-1)
      end if
    end do
    
    !化学種の ID を取得
    do s =1, SpcWetNum
      SpcWetID(s) = ChemData_OneSpcID( Symbol(s) )
    end do
    
    !分子量を保管
    do s = 1, SpcWetNum
      MolWtWet(s) = ChemData_MolWt(SpcWetID(s))
    end do

    !----------------------------------------------------------
    ! 確認
    !----------------------------------------------------------
    if (cpurank == 0) then
      call MessageNotify( "M", &
        & "basicset_init", "Grav = %f",     d=(/Grav/) )
      call MessageNotify( "M", &
        & "basicset_init", "TempSfc = %f",  d=(/TempSfc/) )
      call MessageNotify( "M", &
        & "basicset_init", "PressSfc = %f", d=(/PressSfc/) )
      call MessageNotify( "M", &
        & "basicset_init", "PressBasis = %f", d=(/PressBasis/))
      
      do s = 1, SpcDryNum
        call MessageNotify( "M", &
          &  "basicset_init", "SpcDryID = %d",      i=(/SpcDryID(s)/))
        call MessageNotify( "M", &
          &  "basicset_init", "SpcDrySymbol = %c", c1=trim(SpcDrySymbol(s)))
        call MessageNotify( "M", &
          &  "basicset_init", "SpcDryMolFr = %f",   d=(/SpcDryMolFr(s)/))
      end do
      
      call MessageNotify( "M", "basicset_init", "CpDry = %f",    d=(/CpDry/) )
      call MessageNotify( "M", "basicset_init", "CpDryMol = %f", d=(/CpDryMol/) )
      call MessageNotify( "M", "basicset_init", "CvDry = %f",    d=(/CvDry/) )
      call MessageNotify( "M", "basicset_init", "GasRDry = %f",  d=(/GasRDry/) )
      call MessageNotify( "M", "basicset_init", "MolWtDry = %f", d=(/MolWtDry/) )
      
      do s = 1, SpcWetNum
        call MessageNotify( "M", &
          & "basicset_init", "SpcWetID = %d",     i=(/SpcWetID(s)/) )
        call MessageNotify( "M", &
          & "basicset_init", "SpcWetSymbol = %c", c1=trim(SpcWetSymbol(s)) )
        call MessageNotify( "M", &
          & "basicset_init", "SpcWetMolFr = %f",  d=(/SpcWetMolFr(s)/) )
        call MessageNotify( "M", &
          & "basicset_init", "MolWtWet = %f",     d=(/MolWtWet(s)/) )
      end do
      
      call MessageNotify( "M", &
        & "basicset_init", "Tropopause = %f ", d=(/Tropopause/) )
      call MessageNotify( "M", &
        & "basicset_init", "EnvType = %c", c1=trim(EnvType) )
      call MessageNotify( "M", & 
        & "basicset_init", "Humidity = %f", d=(/Humidity/)  )
    end if

  end subroutine BasicSet_Init

end module BasicSet
