!= Module StoreSet
!
! Authors::   SUGIYAMA Ko-ichiro, ODAKA Masatsugu
! Version::   $Id: storeset_3d.f90,v 1.2 2007/08/06 16:08:26 odakker Exp $ 
! Tag Name::  $Name: arare4-20071012 $
! Copyright:: Copyright (C) GFD Dennou Club, 2006. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!
!== Overview 
!
!積算値を保管するための変数型モジュール
!
!== Error Handling
!
!== Known Bugs
!
!== Note
!
!== Future Plans
!

module storeset_3d
  !
  !積算値を保管するための変数型モジュール.
  !
  use dc_types, only : DP
  use xyz_base_module, only: a_MeanXY_aaa => z_AvrXY_xyz
  
  !モジュールの読み込み
  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 方向の物理領域の上限
    &                  RegYMin,     & ! x 方向の物理領域の下限
    &                  RegYMax        ! x 方向の物理領域の上限
  use TimeSet, only:   TimeDisp,    & ! 出力時間間隔
    &                  DelTimeLong    ! 長い時間ステップ

  !暗黙の型宣言禁止
  implicit none

  !属性の指定
  private

  !公開要素
  public StoreSet_Init, StoreMeanXY, StoreClean
  public z_Adv,  z_Turb, z_Disp, z_Diff, z_Rad, &
    &    z_Cond, z_Flux, z_Damp
!  public z_Stab, z_StabTemp, z_StabMolWt, za_MixRt
  public StoreAdv,  StoreTurb, StoreDisp, StoreDiff, StoreRad, &
    &    StoreCond, StoreFlux, StoreDamp
!  public StoreStab, StoreMixRt
  public aa_MeanXY_aaaa

  !変数
  real(DP), allocatable :: z_Adv(:)
  real(DP), allocatable :: z_Turb(:)
  real(DP), allocatable :: z_Disp(:)
  real(DP), allocatable :: z_Diff(:)
  real(DP), allocatable :: z_Rad(:)
  real(DP), allocatable :: z_Damp(:)
  real(DP), allocatable :: z_Cond(:)
  real(DP), allocatable :: z_Flux(:)
  real(DP), allocatable :: xyz_Adv(:,:,:)
  real(DP), allocatable :: xyz_Turb(:,:,:)
  real(DP), allocatable :: xyz_Disp(:,:,:)
  real(DP), allocatable :: xyz_Diff(:,:,:)
  real(DP), allocatable :: xyz_Rad(:,:,:)
  real(DP), allocatable :: xyz_Damp(:,:,:)
  real(DP), allocatable :: xyz_Cond(:,:,:)
  real(DP), allocatable :: xyz_Flux(:,:,:)
!  real(DP), allocatable :: z_Stab(:)
!  real(DP), allocatable :: z_StabTemp(:)
!  real(DP), allocatable :: z_StabMolWt(:)
!  real(DP), allocatable :: xyz_Stab1(:,:,:)
!  real(DP), allocatable :: xyz_Stab2(:,:,:)
!  real(DP), allocatable :: xyz_Stab3(:,:,:)
!  real(DP), allocatable :: za_MixRt(:,:)
!  real(DP), allocatable :: xyza_MixRt1(:,:,:,:)
  
  !save 属性
  save xyz_Adv,  xyz_Turb, xyz_Disp, xyz_Diff, xyz_Rad, &
    &  xyz_Cond, xyz_Flux, xyz_Damp
!  save xyz_Stab1, xyz_Stab2, xyz_Stab3, xyza_MixRt1

contains

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

    allocate(     &
      & z_Adv(DimZMin:DimZMax),  & 
      & z_Turb(DimZMin:DimZMax), &
      & z_Disp(DimZMin:DimZMax), &
      & z_Diff(DimZMin:DimZMax), &
      & z_Rad(DimZMin:DimZMax),  &
      & z_Damp(DimZMin:DimZMax), &
      & z_Cond(DimZMin:DimZMax), &
      & z_Flux(DimZMin:DimZMax), &
      & xyz_Adv(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax),  & 
      & xyz_Turb(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax), &
      & xyz_Disp(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax), &
      & xyz_Diff(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax), &
      & xyz_Rad(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax),  &
      & xyz_Damp(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax), &
      & xyz_Cond(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax), &
      & xyz_Flux(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax) &
      !
!      & z_Stab(DimZMin:DimZMax),      &
!      & z_StabTemp(DimZMin:DimZMax),  &
!      & z_StabMolWt(DimZMin:DimZMax), &
!      & xyz_Stab1(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax), &
!      & xyz_Stab2(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax), &
!      & xyz_Stab3(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax), &
      !
!      & za_MixRt(DimZMin:DimZMax, SpcNum), &
!      & xyza_MixRt1(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax, SpcNum) &
      &  )
    
    z_Adv  = 0.0d0
    z_Turb = 0.0d0
    z_Diff = 0.0d0
    z_Disp = 0.0d0
    z_Rad  = 0.0d0
    z_Damp = 0.0d0
    z_Cond = 0.0d0
    z_Flux = 0.0d0

    xyz_Adv  = 0.0d0
    xyz_Turb = 0.0d0
    xyz_Diff = 0.0d0
    xyz_Disp = 0.0d0
    xyz_Rad  = 0.0d0
    xyz_Damp = 0.0d0
    xyz_Cond = 0.0d0
    xyz_Flux = 0.0d0
   
!    z_Stab      = 0.0d0
!    z_StabTemp  = 0.0d0
!    z_StabMolWt = 0.0d0

!    xyz_Stab1 = 0.0d0
!    xyz_Stab2 = 0.0d0
!    xyz_Stab3 = 0.0d0

!    za_MixRt  = 0.0d0
!    xyza_MixRt1 = 0.0d0

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


  subroutine StoreClean( )
    !保管した値のクリアー
    
    z_Adv  = 0.0d0
    z_Turb = 0.0d0
    z_Diff = 0.0d0
    z_Disp = 0.0d0
    z_Rad  = 0.0d0
    z_Damp = 0.0d0
    z_Cond = 0.0d0
    z_Flux = 0.0d0

    xyz_Adv  = 0.0d0
    xyz_Turb = 0.0d0
    xyz_Diff = 0.0d0
    xyz_Disp = 0.0d0
    xyz_Rad  = 0.0d0
    xyz_Damp = 0.0d0
    xyz_Cond = 0.0d0
    xyz_Flux = 0.0d0
   
!    z_Stab      = 0.0d0
!    z_StabTemp  = 0.0d0
!    z_StabMolWt = 0.0d0

!    xyz_Stab1 = 0.0d0
!    xyz_Stab2 = 0.0d0
!    xyz_Stab3 = 0.0d0

!    za_MixRt  = 0.0d0
!    xyza_MixRt1 = 0.0d0

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


  subroutine StoreMeanXY( )
    !保管した値の水平平均値 [K/s]
    real(DP) :: CalNum

    CalNum = TimeDisp / DelTimeLong
    
    z_Adv  = a_MeanXY_aaa( xyz_Adv )   / CalNum
    z_Turb = a_MeanXY_aaa( xyz_Turb )  / CalNum
    z_Diff = a_MeanXY_aaa( xyz_Diff )  / CalNum
    z_Disp = a_MeanXY_aaa( xyz_Disp )  / CalNum
    z_Rad  = a_MeanXY_aaa( xyz_Rad  )  / CalNum
    z_Damp = a_MeanXY_aaa( xyz_Damp )  / CalNum
    z_Cond = a_MeanXY_aaa( xyz_Cond )  / CalNum
    z_Flux = a_MeanXY_aaa( xyz_Flux )  / CalNum

!    z_Stab      = a_MeanXY_aaa( xyz_Stab1 ) / CalNum
!    z_StabTemp  = a_MeanXY_aaa( xyz_Stab2 ) / CalNum
!    z_StabMolWt = a_MeanXY_aaa( xyz_Stab3 ) / CalNum

!    za_MixRt    = aa_MeanXY_aaaa( xyza_MixRt1 ) / CalNum

    !描画する際に対数プロットをするので, 値にゼロが入って欲しくない
!    where ( za_MixRt < 1.0d-20 )
!      za_MixRt = 1.0d-20
!    end where

  end subroutine StoreMeanXY


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

    implicit none

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

    Work2  = xyz_Adv + Work
    xyz_Adv = Work2

  end subroutine StoreAdv


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

    implicit none

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

    Work2   = xyz_Turb + Work
    xyz_Turb = Work2

  end subroutine StoreTurb


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

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

    Work2   = xyz_Diff + Work
    xyz_Diff = Work2

  end subroutine StoreDiff


  subroutine StoreDisp( Work )
    !散逸加熱項の保管

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

    Work2   = xyz_Disp + Work
    xyz_Disp = Work2

  end subroutine StoreDisp


  subroutine StoreRad( Work )
    !放射冷却項の保管

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

    Work2  = xyz_Rad + Work
    xyz_Rad = Work2

  end subroutine StoreRad


  subroutine StoreDamp( Work )
    !ダンピング項の保管

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

    Work2   = xyz_Damp + Work
    xyz_Damp = Work2

  end subroutine StoreDamp


  subroutine StoreCond( Work )
    !潜熱・蒸発熱の保管

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

    Work2   = xyz_Cond + Work
    xyz_Cond = Work2

  end subroutine StoreCond


  subroutine StoreFlux( Work )
    !地表面フラックスの保管

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

    Work2   = xyz_Flux + Work
    xyz_Flux = Work2

  end subroutine StoreFlux


!  subroutine StoreStab( Work1, Work2, Work3 )
!    !安定度の保管
!
!    implicit none
!    
!    real(DP), intent(in)  :: Work1(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax)
!    real(DP), intent(in)  :: Work2(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax)
!    real(DP), intent(in)  :: Work3(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax)
!    real(DP)              :: WorkA(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax)
!    real(DP)              :: WorkB(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax)
!    real(DP)              :: WorkC(DimXMin:DimXMax,DimYMin:DimYMax,DimZMin:DimZMax)

!    WorkA    = Work1 + xyz_Stab1 
!    xyz_Stab1 = WorkA

!    WorkB    =  Work2 + xyz_Stab2
!    xyz_Stab2 = WorkB

!    WorkC    = Work3 + xyz_Stab3
!    xyz_Stab3 = WorkC

!  end subroutine StoreStab


!  subroutine StoreMixRt( Work1 )
!    !Store Mixing ratio of species
!
!    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_MixRt1
!    xyza_MixRt1 = WorkA
!
!  end subroutine StoreMixRt


  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)
                                     !水平平均値
    integer               :: i

    do i = 1, SpcNum
      aa_MeanXY_aaaa(:,i) = a_MeanXY_aaa(var(:,:,:,i))
    end do
  
  end function aa_MeanXY_aaaa
  

  
end module storeset_3d
