!= Module StoreMixRt_3d
!
! Authors::   SUGIYAMA Ko-ichiro, ODAKA Masatsugu
! Version::   $Id: storemixrt_3d.f90,v 1.1 2008-06-19 16:47:53 odakker Exp $ 
! Tag Name::  $Name: arare4-20080627 $
! Copyright:: Copyright (C) GFD Dennou Club, 2008. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!
!== Overview 
!
!混合比に関する積算値を保管するための変数型モジュール
!
!== Error Handling
!
!== Known Bugs
!
!== Note
!
!== Future Plans
!

module StoreMixRt_3d
  !
  !積算値を保管するための変数型モジュール.
  !
  use dc_types,  only : DP
  use dc_message,only : MessageNotify

  !モジュールの読み込み
  use gridset_3d, only:DimXMin,     & ! x 方向の配列の下限
    &                  DimXMax,     & ! x 方向の配列の上限
    &                  DimYMin,     & ! y 方向の配列の下限
    &                  DimYMax,     & ! y 方向の配列の上限
    &                  DimZMin,     & ! z 方向の配列の下限
    &                  DimZMax,     & ! z 方向の配列の上限
    &                  SpcNum,      & ! number of species
    &                  RegXMin,     & ! x 方向の物理領域の下限
    &                  RegXMax,     & ! x 方向の物理領域の上限
    &                  RegYMin,     & ! x 方向の物理領域の下限
    &                  RegYMax        ! x 方向の物理領域の上限
  use TimeSet, only:   TimeDisp,    & ! 出力時間間隔
    &                  DelTimeLong    ! 長い時間ステップ

  !暗黙の型宣言禁止
  implicit none

  !属性の指定
  private

  !公開要素
  public StoreMixRt_Init, StoreMixRtMeanXY, StoreMixRtClean
  public za_Adv,  za_Turb,  za_Diff, za_Flux, za_Rain, &
    &    za_Cond, za_Fill1, za_Fill2
  public StoreMixRtAdv, StoreMixRtTurb, StoreMixRtDiff, StoreMixRtFlux, StoreMixRtRain, &
    &    StoreMixRtCond, StoreMixRtFill1, StoreMixRtFill2

  !公開変数
  real(DP), allocatable :: za_Adv(:,:)
  real(DP), allocatable :: za_Turb(:,:)
  real(DP), allocatable :: za_Diff(:,:)
  real(DP), allocatable :: za_Flux(:,:)
  real(DP), allocatable :: za_Rain(:,:)
  real(DP), allocatable :: za_Fill1(:,:)
  real(DP), allocatable :: za_Fill2(:,:)
  real(DP), allocatable :: za_Cond(:,:)
!  real(DP), allocatable :: za_Asln(:,:)
  real(DP), allocatable :: xyza_Adv (:,:,:,:)
  real(DP), allocatable :: xyza_Turb(:,:,:,:)
  real(DP), allocatable :: xyza_Diff(:,:,:,:)
  real(DP), allocatable :: xyza_Flux(:,:,:,:)
  real(DP), allocatable :: xyza_Rain(:,:,:,:)
  real(DP), allocatable :: xyza_Fill1(:,:,:,:)
  real(DP), allocatable :: xyza_Fill2(:,:,:,:)
  real(DP), allocatable :: xyza_Cond(:,:,:,:)
!  real(DP), allocatable :: xyza_Asln(:,:,:,:)
!  real(DP)              :: CalNum

  save xyza_Adv,  xyza_Turb,  xyza_Diff, xyza_Flux, xyza_Rain, &
    &  xyza_Cond, xyza_Fill1, xyza_Fill2
  save za_Adv,  za_Turb,  za_Diff, za_Flux, za_Rain, &
    &  za_Cond, za_Fill1, za_Fill2
  
contains

  subroutine StoreMixRt_Init( )
    !初期化ルーチン

    allocate(     &
      & za_Adv  (DimZMin:DimZMax, SpcNum),   & 
      & za_Turb (DimZMin:DimZMax, SpcNum),  &
      & za_Diff (DimZMin:DimZMax, SpcNum),  &
      & za_Flux (DimZMin:DimZMax, SpcNum),  &
      & za_Rain (DimZMin:DimZMax, SpcNum),  &
      & za_Fill1(DimZMin:DimZMax, SpcNum), &
      & za_Fill2(DimZMin:DimZMax, SpcNum), &
!      & za_Asln (DimZMin:DimZMax, SpcNum), &
      & za_Cond (DimZMin:DimZMax, SpcNum), &
      & xyza_Adv  (DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum), & 
      & xyza_Turb (DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum), &
      & xyza_Diff (DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum), &
      & xyza_Flux (DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum), &
      & xyza_Rain (DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum), &
      & xyza_Fill1(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum), &
      & xyza_Fill2(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum), &
!      & xyza_Asln(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum), &
      & xyza_Cond(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum) &
      &  )
    
    call StoreMixRtClean()

  end subroutine StoreMixRt_Init


  subroutine StoreMixRtClean( )
    !保管した値のクリアー
    
    za_Adv  = 0.0d0
    za_Turb = 0.0d0
    za_Diff = 0.0d0
    za_Flux = 0.0d0
    za_Rain = 0.0d0
    za_Fill1 = 0.0d0
    za_Fill2 = 0.0d0
    za_Cond = 0.0d0
!    za_Asln = 0.0d0

    xyza_Adv  = 0.0d0
    xyza_Turb = 0.0d0
    xyza_Diff = 0.0d0
    xyza_Flux = 0.0d0
    xyza_Rain = 0.0d0
    xyza_Fill1 = 0.0d0
    xyza_Fill2 = 0.0d0
    xyza_Cond = 0.0d0
!    xyza_Asln = 0.0d0

!    CalNum  = 1.0d-40   !ゼロ割を禁止
  end subroutine StoreMixRtClean


  subroutine StoreMixRtMeanXY( )
    !保管した値の水平平均値
 
    real(DP) :: CalNum

    CalNum = TimeDisp / DelTimeLong
   
    za_Adv   = aa_MeanXY_aaaa( xyza_Adv )   / CalNum
    za_Turb  = aa_MeanXY_aaaa( xyza_Turb )  / CalNum
    za_Diff  = aa_MeanXY_aaaa( xyza_Diff )  / CalNum
    za_Flux  = aa_MeanXY_aaaa( xyza_Flux )  / CalNum
    za_Rain  = aa_MeanXY_aaaa( xyza_Rain )  / CalNum
    za_Fill1 = aa_MeanXY_aaaa( xyza_Fill1 ) / CalNum
    za_Fill2 = aa_MeanXY_aaaa( xyza_Fill2 ) / CalNum
    za_Cond  = aa_MeanXY_aaaa( xyza_Cond )  / CalNum
!    za_Asln  = aa_MeanXY_aaaa( xyza_Asln )  / CalNum

  end subroutine StoreMixRtMeanXY


  subroutine StoreMixRtAdv( Work )
    !移流項の保管

    implicit none

    real(DP), intent(in)  :: Work(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
    real(DP)              :: Work2(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)

    Work2  = xyza_Adv + Work
    xyza_Adv = Work2

!    CalNum = CalNum + 1

  end subroutine StoreMixRtAdv


  subroutine StoreMixRtTurb( Work )
    !乱流項の保管

    implicit none

    real(DP), intent(in)  :: Work(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
    real(DP)              :: Work2(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)

    Work2   = xyza_Turb + Work
    xyza_Turb = Work2

  end subroutine StoreMixRtTurb


  subroutine StoreMixRtDiff( Work )
    !数値拡散項の保管

    implicit none
    
    real(DP), intent(in)  :: Work(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
    real(DP)              :: Work2(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)

    Work2   = xyza_Diff + Work
    xyza_Diff = Work2

  end subroutine StoreMixRtDiff


  subroutine StoreMixRtRain( Work )
    !降雨の重力落下に伴う変化

    implicit none
    
    real(DP), intent(in)  :: Work(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
    real(DP)              :: Work2(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)

    Work2   = xyza_Rain + Work
    xyza_Rain = Work2

  end subroutine StoreMixRtRain


  subroutine StoreMixRtFlux( Work )
    !地表面フラックスによる変化

    implicit none
    
    real(DP), intent(in)  :: Work(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
    real(DP)              :: Work2(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)

    Work2  = xyza_Flux + Work
    xyza_Flux = Work2

  end subroutine StoreMixRtFlux


  subroutine StoreMixRtCond( Work )
    !凝結に伴う変化

    implicit none
    
    real(DP), intent(in)  :: Work(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
    real(DP)              :: Work2(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)

    Work2   = xyza_Cond + Work
    xyza_Cond = Work2

  end subroutine StoreMixRtCond


!  subroutine StoreMixRtAsln( Work )
!    !アッセリン時間フィルタに伴う変化量を保管
!
!    implicit none
!    
!    real(DP), intent(in)  :: Work(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
!    real(DP)              :: Work2(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
!
!    Work2   = xyza_Asln + Work
!    xyza_Asln = Work2
!
!  end subroutine StoreMixRtAsln


  subroutine StoreMixRtFill1( Work1 )
    !穴埋めプログラムによる変化

    implicit none
    
    real(DP), intent(in)  :: Work1(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
    real(DP)              :: WorkA(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)

    WorkA     = Work1 + xyza_Fill1
    xyza_Fill1 = WorkA

  end subroutine StoreMixRtFill1


  subroutine StoreMixRtFill2( Work1 )
    !穴埋めプログラム(2)による変化

    implicit none
    
    real(DP), intent(in)  :: Work1(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
    real(DP)              :: WorkA(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)

    WorkA      = Work1 + xyza_Fill2
    xyza_Fill2  = WorkA

  end subroutine StoreMixRtFill2


  function aa_MeanXY_aaaa( var ) 
    !
    ! 水平平均値の計算
    !
    
    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(DP), intent(in)  :: var(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
                                     !平均演算の対象となる変数
    real(DP)              :: aa_MeanXY_aaaa(DimZMin:DimZMax, SpcNum)
                                     !水平平均値
    real(DP)              :: aaa_work(DimYMin:DimYMax,DimZMin:DimZMax, SpcNum)
                                     !X 方向平均値

    aaa_work = aaa_MeanX_aaaa(var) 

    aa_MeanXY_aaaa = sum( aaa_work(RegYMin+1:RegYMax,:,:), 1 ) &
      &           / real(RegYMax - RegYMin, 8) 
    
  end function aa_MeanXY_aaaa
  
  function aaa_MeanX_aaaa( var ) 
    !
    ! X 方向平均値の計算
    !
    
    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(DP), intent(in)  :: var(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax,SpcNum)
                                     !平均演算の対象となる変数
    real(DP)             :: aaa_MeanX_aaaa(DimYMin:DimYMax,DimZMin:DimZMax,SpcNum)
                                     !X 方向平均値

    aaa_MeanX_aaaa = sum( var(RegXMin:RegXMax, :, :, :), 1 ) &
      &           / real(RegXMax - RegXMin + 1 , 8) 

  end function aaa_MeanX_aaaa
  
end module StoreMixRt_3d
