!= デフォルトの基本場を設定するための変数参照型モジュール
!
! Authors::   SUGIYAMA Ko-ichiro, ODAKA Masatsugu
! Version::   $Id: basicset.f90,v 1.18 2014/07/08 01:05:32 sugiyama Exp $
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2007. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!

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

  !モジュール読み込み
  use dc_types,   only:  DP
  use gridset,    only:  imin,       &! 配列の X 方向の下限
    &                    imax,       &! 配列の X 方向の上限
    &                    jmin,       &! 配列の Z 方向の下限
    &                    jmax,       &! 配列の Z 方向の上限
    &                    kmin,       &! 配列の Z 方向の下限
    &                    kmax,       &! 配列の Z 方向の上限
    &                    ncmax        ! 化学種の数
  use composition, only: GasNum,     &!気体の数
    &                    IdxG,       &!気体の配列添え字
    &                    MolWtWet     !凝縮成分の分子量

  !暗黙の型宣言禁止
  implicit none

  !save 属性
  private

  !Public Interface
  real(DP), allocatable, save, public :: xz_DensBasicZ(:,:)    !密度
  real(DP), allocatable, save, public :: pz_DensBasicZ(:,:)    !密度
  real(DP), allocatable, save, public :: xqz_DensBasicZ(:,:)    !密度
  real(DP), allocatable, save, public :: xr_DensBasicZ(:,:)    !密度
  real(DP), allocatable, save, public :: xz_PressBasicZ(:,:)   !無次元圧力
  real(DP), allocatable, save, public :: xz_ExnerBasicZ(:,:)   !無次元圧力
  real(DP), allocatable, save, public :: xz_TempBasicZ(:,:)    !温度
  real(DP), allocatable, save, public :: xz_PotTempBasicZ(:,:)   !温位
  real(DP), allocatable, save, public :: xr_PotTempBasicZ(:,:)   !温位
  real(DP), allocatable, save, public :: xz_VPotTempBasicZ(:,:)  !仮温位
  real(DP), allocatable, save, public :: pz_VPotTempBasicZ(:,:)  !仮温位
  real(DP), allocatable, save, public :: xqz_VPotTempBasicZ(:,:)  !仮温位
  real(DP), allocatable, save, public :: xr_VPotTempBasicZ(:,:)  !仮温位
  real(DP), allocatable, save, public :: xz_VelSoundBasicZ(:,:)!音速
  real(DP), allocatable, save, public :: xz_VelSW(:,:)   !音速
  real(DP), allocatable, save, public :: xza_MixRtBasicZ(:,:,:) !凝縮成分混合比
  real(DP), allocatable, save, public :: xz_EffMolWtBasicZ(:,:)!分子量効果
  real(DP), allocatable, save, public :: xz_MixRtBasicZPerMolWt(:,:)
                              !基本場の混合比 / 分子量 の総和
  real(DP), allocatable, save, public :: xr_MixRtBasicZPerMolWt(:,:)
                              !基本場の混合比 / 分子量 の総和
  real(DP), allocatable, save, public :: xz_MixRtBasicZ(:,:)
                              !基本場の混合比の総和
  real(DP), allocatable, save, public :: xr_MixRtBasicZ(:,:)
                              !基本場の混合比の総和
  real(DP), allocatable, save, public :: z_TempBasicZ(:)         !温度

  public basicset_init

contains

!!!-----------------------------------------------------------------!!!
  subroutine basicset_init(                                     &
    &   xz_Press, xz_Exner, xz_Temp, xz_PotTemp, xz_Dens,    & 
    &   xz_VelSound, xza_MixRt, xz_EffMolWt &
    & )
    !
    != 基本場の値を外部から取得する. 
    !
    ! dry の場合は混合比や乾燥成分と凝結成分の存在比を陽に使わないので,
    ! これらの変数は optional にしている. 
    !
    
    !入力変数
    real(DP), intent(in) :: xz_Press(imin:imax,kmin:kmax)
    real(DP), intent(in) :: xz_Exner(imin:imax,kmin:kmax)
    real(DP), intent(in) :: xz_Temp(imin:imax,kmin:kmax)
    real(DP), intent(in) :: xz_PotTemp(imin:imax,kmin:kmax)
    real(DP), intent(in) :: xz_Dens(imin:imax,kmin:kmax)
    real(DP), intent(in) :: xz_VelSound(imin:imax,kmin:kmax)
    real(DP), intent(in), optional :: xza_MixRt(imin:imax,kmin:kmax,ncmax)
    real(DP), intent(in), optional :: xz_EffMolWt(imin:imax,kmin:kmax)
    real(DP)             :: xza_MixRtBasicZPerMolWt(imin:imax,kmin:kmax,GasNum)
    integer              :: s, k, f

    ! 配列の初期化
    call basicset_array_init
    
    !値の入力
    xz_PressBasicZ    = xz_Press
    xz_ExnerBasicZ    = xz_Exner
    xz_TempBasicZ     = xz_Temp
    xz_PotTempBasicZ    = xz_PotTemp
    xz_DensBasicZ     = xz_Dens
    xz_VelSoundBasicZ = xz_VelSound
    xz_VelSW      = xz_VelSound  ! 配列名を短くするために. 

    if (present(xz_EffMolWt)) xz_EffMolWtBasicZ = xz_EffMolWt

    if (present(xza_MixRt)) then 
      xza_MixRtBasicZ = xza_MixRt
      xza_MixRtBasicZPerMolWt = 0.0d0

      do s = 1, GasNum
        xza_MixRtBasicZPerMolWt(:,:,s) = &
          & xza_MixRtBasicZ(:,:,IdxG(s)) / MolWtWet(IdxG(s))
      end do

      xz_MixRtBasicZPerMolWt = sum(xza_MixRtBasicZPerMolWt, 3) 
      xz_MixRtBasicZ         = sum(xza_MixRtBasicZ, 3) 

      do k = kmin, kmax-1
        xr_MixRtBasicZPerMolWt(:,k) =       &
          & (                               &
          &  + xz_MixRtBasicZPerMolWt(:,k)  &
          &  + xz_MixRtBasicZPerMolWt(:,k+1)&
          & ) * 5.0d-1

        xr_MixRtBasicZ(:,k) =               &
          & (                               &
          &  + xz_MixRtBasicZ(:,k)          &
          &  + xz_MixRtBasicZ(:,k+1)        &
          & ) * 5.0d-1
      end do

    end if

    xz_VPotTempBasicZ = xz_PotTempBasicZ / xz_EffMolWtBasicZ

    do k = kmin, kmax-1    
      xr_PotTempBasicZ(:,k) = &
        & ( xz_PotTempBasicZ(:,k) + xz_PotTempBasicZ(:,k+1) ) * 5.0d-1

      xr_VPotTempBasicZ(:,k) = &
        & ( xz_VPotTempBasicZ(:,k) + xz_VPotTempBasicZ(:,k+1) ) * 5.0d-1

      xr_DensBasicZ(:,k) = &
        & ( xz_DensBasicZ(:,k) + xz_DensBasicZ(:,k+1) ) * 5.0d-1
    end do

    ! 水平一様なので, 平均操作は必要ない
    !
    pz_DensBasicZ   = xz_Dens
    xqz_DensBasicZ  = xz_Dens
    pz_VPotTempBasicZ = xz_VPotTempBasicZ 
    xqz_VPotTempBasicZ = xz_VPotTempBasicZ 

    ! 一次元の変数を用意しておく
!    z_TempBasicZ = xz_TempBasicZ(1,:)

  end subroutine basicset_init


  subroutine basicset_array_init
    !
    ! *BasicZ な配列の初期化
    !

    allocate( & 
      & xz_DensBasicZ(imin:imax,kmin:kmax), &
      & pz_DensBasicZ(imin:imax,kmin:kmax), &
      & xqz_DensBasicZ(imin:imax,kmin:kmax), &
      & xr_DensBasicZ(imin:imax,kmin:kmax), &
      & xz_PressBasicZ(imin:imax,kmin:kmax), &
      & xz_ExnerBasicZ(imin:imax,kmin:kmax), &
      & xz_TempBasicZ(imin:imax,kmin:kmax), &
      & xz_PotTempBasicZ (imin:imax,kmin:kmax), &
      & xr_PotTempBasicZ (imin:imax,kmin:kmax), &
      & xz_VPotTempBasicZ (imin:imax,kmin:kmax), &
      & pz_VPotTempBasicZ (imin:imax,kmin:kmax), &
      & xqz_VPotTempBasicZ (imin:imax,kmin:kmax), &
      & xr_VPotTempBasicZ (imin:imax,kmin:kmax), &
      & xz_VelSoundBasicZ(imin:imax,kmin:kmax), &
      & xz_VelSW(imin:imax,kmin:kmax), &
      & xza_MixRtBasicZ(imin:imax,kmin:kmax,ncmax), &
      & xz_EffMolWtBasicZ(imin:imax,kmin:kmax)  &
      & )
    allocate( &
      & xr_MixRtBasicZPerMolWt(imin:imax,kmin:kmax),           &
      & xz_MixRtBasicZPerMolWt(imin:imax,kmin:kmax),           &
      & xr_MixRtBasicZ(imin:imax,kmin:kmax),                   &
      & xz_MixRtBasicZ(imin:imax,kmin:kmax)                    &
      & )

    ! 値の確定
    xz_DensBasicZ     = 0.0d0
    xz_PressBasicZ    = 0.0d0   
    xz_ExnerBasicZ    = 0.0d0   
    xz_TempBasicZ     = 0.0d0   
    xz_PotTempBasicZ  = 0.0d0
    xz_VPotTempBasicZ = 0.0d0
    xz_VelSoundBasicZ = 0.0d0
    xza_MixRtBasicZ   = 0.0d0
    xz_EffMolWtBasicZ = 1.0d0 ! dry の場合は必ず 1.0

    xr_MixRtBasicZPerMolWt = 0.0d0
    xz_MixRtBasicZPerMolWt = 0.0d0
    xr_MixRtBasicZ = 0.0d0
    xz_MixRtBasicZ = 0.0d0

  end subroutine basicset_array_init
  
end module basicset
