!= Module Boundary
!
! Authors::   SUGIYAMA Ko-ichiro
! Version::   $Id: boundary.f90,v 1.4 2006/09/21 02:35:16 odakker Exp $ 
! Tag Name::  $Name: arare4-20060922 $
! Copyright:: Copyright (C) GFD Dennou Club, 2006. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!
!== Overview 
!
!境界条件を与えるためのモジュール. 
!引数 type に指定された境界条件から, 「のり代」の部分の値を設定する
!
!== Error Handling
!
!== Known Bugs
!
!== Note
!
!水平鉛直に摩擦無し境界とする設定は, 移流のテスト計算用であることに注意.
!
!== Future Plans
!

module boundary

  !モジュール読み込み
  use gridset, only: MarginX,       &! x 方向の境界のグリッド数
    &                MarginZ,       &! z 方向の境界のグリッド数
    &                DimXMin,       &! x 方向の配列の下限
    &                DimXMax,       &! x 方向の配列の上限
    &                DimZMin,       &! z 方向の配列の下限
    &                DimZMax,       &! z 方向の配列の上限
    &                RegXMin,       &! x 方向の物理領域の下限
    &                RegXMax,       &! x 方向の物理領域の上限
    &                RegZMin,       &! z 方向の物理領域の下限
    &                RegZMax,       &! z 方向の物理領域の上限
    &                SpcNum          ! 化学種の数
     
  !暗黙の型宣言禁止
  implicit none

  !private 属性にする
  private

  !関数を public にする
  public xza_BoundaryXCyc_xza
  public xz_BoundaryXCyc_xz
  public pz_BoundaryXCyc_pz
  public xr_BoundaryXCyc_xr

  public xza_BoundaryZSym_xza
  public xz_BoundaryZSym_xz
  public pz_BoundaryZSym_pz
  public xr_BoundaryZSym_xr

  public xza_BoundaryZAntiSym_xza
  public xz_BoundaryZAntiSym_xz
  public pz_BoundaryZAntiSym_pz
  public xr_BoundaryZAntiSym_xr

  !関数の定義. 2 度 3 度同じような関数を定義するのは避けるため.
  interface xza_BoundaryXCyc_xza
    module procedure aaa_BoundaryXCyc_aaa
  end interface
  interface xz_BoundaryXCyc_xz
    module procedure aa_BoundaryXCyc_aa
  end interface
  interface pz_BoundaryXCyc_pz
    module procedure aa_BoundaryXCyc_aa
  end interface 
  interface xr_BoundaryXCyc_xr
    module procedure aa_BoundaryXCyc_aa
  end interface 

  interface xza_BoundaryZSym_xza
    module procedure aza_BoundaryZSym_aza
  end interface 
  interface xz_BoundaryZSym_xz
    module procedure az_BoundaryZSym_az
  end interface 
  interface pz_BoundaryZSym_pz
    module procedure az_BoundaryZSym_az
  end interface
  interface xr_BoundaryZSym_xr
    module procedure ar_BoundaryZSym_ar
  end interface 
  
  interface xza_BoundaryZAntiSym_xza
    module procedure aza_BoundaryZAntiSym_aza
  end interface 
  interface xz_BoundaryZAntiSym_xz
    module procedure az_BoundaryZAntiSym_az
  end interface 
  interface pz_BoundaryZAntiSym_pz
    module procedure az_BoundaryZAntiSym_az
  end interface
  interface xr_BoundaryZAntiSym_xr
    module procedure ar_BoundaryZAntiSym_ar
  end interface 
  
contains

!!!---------------------------------------------------------------------!!!
  function aa_BoundaryXCyc_aa( aa_Var )
    !
    ! x 方向に「周期境界条件」を適用する. 
    ! 格子点, 半格子点においても, 関数の形式は同じ
    !

    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(8)                 :: aa_BoundaryXCyc_aa(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8), intent(inout)  :: aa_Var(DimXMin:DimXMax, DimZMin:DimZMax)
    integer                 :: i
    
    aa_BoundaryXCyc_aa = aa_Var
    
    do i = 0, MarginX
      aa_BoundaryXCyc_aa(RegXMin - i, :) = aa_Var(RegXMax - i, :)
    end do
    do i = 1, MarginX
      aa_BoundaryXCyc_aa(RegXMax + i, :) = aa_Var(RegXMin + i, :) 
    end do
    
  end function aa_BoundaryXCyc_aa


!!!---------------------------------------------------------------------!!!
  function aaa_BoundaryXCyc_aaa( aaa_Var )
    !
    ! x 方向に「周期境界条件」を適用する. 
    ! 格子点, 半格子点においても, 関数の形式は同じ
    !

    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(8)                 :: aaa_BoundaryXCyc_aaa(DimXMin:DimXMax, DimZMin:DimZMax, SpcNum)
    real(8), intent(inout)  :: aaa_Var(DimXMin:DimXMax, DimZMin:DimZMax, SpcNum)
    integer                 :: i
    
    aaa_BoundaryXCyc_aaa = aaa_Var

    do i = 0, MarginX
      aaa_BoundaryXCyc_aaa(RegXMin - i, :, :) = aaa_Var(RegXMax - i, :, :)
    end do
    do i = 1, MarginX
      aaa_BoundaryXCyc_aaa(RegXMax + i, :, :) = aaa_Var(RegXMin + i, :, :) 
    end do
    
  end function aaa_BoundaryXCyc_aaa


!!!---------------------------------------------------------------------!!!
  function az_BoundaryZSym_az( az_Var )
    !
    ! z 方向に半格子ずれた点に存在する変数に対し, 
    ! z 方向に「対称境界条件」を適用する. 
    !

    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(8)                 :: az_BoundaryZSym_az(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8), intent(inout)  :: az_Var(DimXMin:DimXMax, DimZMin:DimZMax)
    integer                 :: k
  
    az_BoundaryZSym_az = az_Var

    do k = 0, MarginZ
      az_BoundaryZSym_az( :, RegZMin - k ) = az_Var( :, RegZMin + 1 + k )
    end do
    do k = 1, MarginZ
      az_BoundaryZSym_az( :, RegZMax + k ) = az_Var( :, RegZMax + 1 - k )
    end do
    
  end function az_BoundaryZSym_az


!!!---------------------------------------------------------------------!!!
  function aza_BoundaryZSym_aza( aza_Var )
    !
    ! z 方向に半格子ずれた点に存在する変数に対し, 
    ! z 方向に「対称境界条件」を適用する. 
    !

    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(8)                 :: aza_BoundaryZSym_aza(DimXMin:DimXMax, DimZMin:DimZMax, SpcNum)
    real(8), intent(inout)  :: aza_Var(DimXMin:DimXMax, DimZMin:DimZMax, SpcNum)
    integer                 :: k
  
    aza_BoundaryZSym_aza = aza_Var

    do k = 0, MarginZ
      aza_BoundaryZSym_aza( :, RegZMin - k, : ) = aza_Var( :, RegZMin + 1 + k, : )
    end do
    do k = 1, MarginZ
      aza_BoundaryZSym_aza( :, RegZMax + k, : ) = aza_Var( :, RegZMax + 1 - k, : )
    end do
    
  end function aza_BoundaryZSym_aza


!!!---------------------------------------------------------------------!!!
  function az_BoundaryZAntiSym_az( az_Var )
    !
    ! z 方向に半格子ずれた点に存在する変数に対し, 
    ! z 方向に「反対称境界条件」を適用する. 
    !

    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(8)                 :: az_BoundaryZAntiSym_az(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8), intent(inout)  :: az_Var(DimXMin:DimXMax, DimZMin:DimZMax)
    integer                 :: k
    
    az_BoundaryZAntiSym_az = az_Var
    
    do k = 0, MarginZ
      az_BoundaryZAntiSym_az( :, RegZMin - k ) = - az_Var( :, RegZMin + 1 + k )
    end do
    do k = 1, MarginZ
      az_BoundaryZAntiSym_az( :, RegZMax + k ) = - az_Var( :, RegZMax + 1 - k )
    end do
    
  end function az_BoundaryZAntiSym_az
  

!!!---------------------------------------------------------------------!!!
  function aza_BoundaryZAntiSym_aza( aza_Var )
    !
    ! z 方向に半格子ずれた点に存在する変数に対し, 
    ! z 方向に「反対称境界条件」を適用する. 
    !

    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(8)                 :: aza_BoundaryZAntiSym_aza(DimXMin:DimXMax, DimZMin:DimZMax, SpcNum)
    real(8), intent(inout)  :: aza_Var(DimXMin:DimXMax, DimZMin:DimZMax, SpcNum)
    integer                 :: k
    
    aza_BoundaryZAntiSym_aza = aza_Var
    
    do k = 0, MarginZ
      aza_BoundaryZAntiSym_aza( :, RegZMin - k, : ) = - aza_Var( :, RegZMin + 1 + k, : )
    end do
    do k = 1, MarginZ
      aza_BoundaryZAntiSym_aza( :, RegZMax + k, : ) = - aza_Var( :, RegZMax + 1 - k, : )
    end do
    
  end function aza_BoundaryZAntiSym_aza
  

!!!---------------------------------------------------------------------!!!
  function ar_BoundaryZSym_ar( ar_Var )
    !
    ! z 方向の格子点上に存在する変数に対し, 
    ! z 方向に「対称境界条件」を適用する. 
    !
    
    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(8)                 :: ar_BoundaryZSym_ar(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8), intent(inout)  :: ar_Var(DimXMin:DimXMax, DimZMin:DimZMax)
    integer                 :: k
  
    ar_BoundaryZSym_ar = ar_Var

    !境界での速度はゼロ
    ar_BoundaryZSym_ar( :, RegZMin ) = 0.0d0
    ar_BoundaryZSym_ar( :, RegZMax ) = 0.0d0
    
    do k = 1, MarginZ
      ar_BoundaryZSym_ar( :, RegZMin - k ) = ar_Var( :, RegZMin + k )
      ar_BoundaryZSym_ar( :, RegZMax + k ) = ar_Var( :, RegZMax - k )
    end do
    
  end function ar_BoundaryZSym_ar


!!!---------------------------------------------------------------------!!!
  function ar_BoundaryZAntiSym_ar( ar_Var )
    !
    ! z 方向の格子点上に存在する変数に対し, 
    ! z 方向に「反対称境界条件」を適用する. 
    !
    
    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(8)                 :: ar_BoundaryZAntiSym_ar(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8), intent(inout)  :: ar_Var(DimXMin:DimXMax, DimZMin:DimZMax)
    integer                 :: k
  
    ar_BoundaryZAntiSym_ar = ar_Var

    !境界での速度はゼロ
    ar_BoundaryZAntiSym_ar( :, RegZMin ) = 0.0d0
    ar_BoundaryZAntiSym_ar( :, RegZMax ) = 0.0d0

    do k = 1, MarginZ
      ar_BoundaryZAntiSym_ar( :, RegZMin - k ) = - ar_Var( :, RegZMin + k )
      ar_BoundaryZAntiSym_ar( :, RegZMax + k ) = - ar_Var( :, RegZMax - k )
    end do
    
  end function ar_BoundaryZAntiSym_ar


end module boundary
