!---------------------------------------------------------------------
!     Copyright (C) GFD Dennou Club, 2006. All rights reserved.
!---------------------------------------------------------------------
!
!= 1 次元 (x 方向) 不等間隔交互格子 有限差分モデル用 境界条件モジュール
!
!* 履歴
!  * 2007/07/15 (小高正嗣) : 3D deepconv へ移植, dc_types を Use.
!  * 2006/05/26 (小高正嗣) : モジュール名称変更
!  * 2006/02/02 (小高正嗣) : 新規作成

module x_bc_module
  != 1 次元 (x 方向) 不等間隔交互格子 有限差分モデル用 境界条件モジュール
  !
  !== 概要
  !
  ! x_bc_module は, 1 次元 (x 方向) 不等間隔交互格子を用いた有限差分法に
  ! 基づく数値モデルのための, 境界条件設定 Fortran 90 副プログラムを提供
  ! する.
  !
  ! このモジュールは x_module の下位モジュールである. 下請けモジュール
  ! として data_type, x_base_module モジュールを用いている. 
  !
  !
  !== 手続きの命名法
  !
  ! 境界条件を設定する副プログラムは
  !
  !   Boundary[境界条件を示す文字列]_(入力配列の次元情報)
  !
  ! のように命名されている. 境界条件を示す文字列は以下の 3 つである.
  !
  !   Sym  : 境界で対称
  !   Asym : 境界で反対称
  !   Cycl : 周期境界 
  ! 

  use dc_types,      only : DBKIND => DP
  use x_base_module, only : im, xmargin, imin, imax
  implicit none

  private
  public :: BoundarySym_x, BoundaryAsym_x, BoundaryCyc_x
  public :: BoundarySym_p, BoundaryAsym_p, BoundaryCyc_p

  interface BoundaryCyc_x
    module procedure BoundaryCyc
  end interface 

  interface BoundaryCyc_p
    module procedure BoundaryCyc
  end interface 

  contains
!--------------------------------------------------------------------
    subroutine BoundarySym_x(x_Var)
      ! 1 次元 (x 方向) 配列に対称境界条件を適用する.

      real(DBKIND),intent(inout) :: x_Var(imin:imax) ! 入出力配列 
      integer                    :: ix               ! ループ添字

      ! 対称境界条件を適用する
      ! 
      !   ex.) im=5, xmargin=2 の場合 (imin=-1, imax=7)
      !
      !   p    -1   0   1   2   3   4   5   6   7 
      !     |-:-|-:-|-:-|-:-|-:-|-:-|-:-|-:-|-:-|
      !   x  -1   0   1   2   3   4   5   6   7
      !     <------->                   <------->  
      !    x_Var(imin:0)     と     x_Var(im+1,imax) の値を更新
      !     
      !   x_Var(0)  = x_Var(1)
      !   x_Var(-1) = x_Var(2)
      !   x_Var(6)  = x_Var(5)
      !   x_Var(7)  = x_Var(4)
      !
      do ix = 1, xmargin
        x_Var(1-ix)  = x_Var(ix)
        x_Var(im+ix) = x_Var(im+1-ix)
      end do

    end subroutine BoundarySym_x
!--------------------------------------------------------------------
    subroutine BoundaryAsym_x(x_Var)
      ! 1 次元 (x 方向) 配列に反対称境界条件を適用する.

      real(DBKIND),intent(inout) :: x_Var(imin:imax) ! 入出力配列 
      integer                    :: ix               ! ループ添字

      ! 反対称境界条件を適用する
      ! 
      !   ex.) im=5, xmargin=2 の場合 (imin=-1, imax=7)
      !
      !   p    -1   0   1   2   3   4   5   6   7 
      !     |-:-|-:-|-:-|-:-|-:-|-:-|-:-|-:-|-:-|
      !   x  -1   0   1   2   3   4   5   6   7
      !     <------->                   <------->  
      !    x_Var(imin:0)     と     x_Var(im+1,imax) の値を更新
      !     
      !   x_Var(0)  = - x_Var(1)
      !   x_Var(-1) = - x_Var(2)
      !   x_Var(6)  = - x_Var(5)
      !   x_Var(7)  = - x_Var(4)
      !
      do ix = 1, xmargin
        x_Var(1-ix)  = - x_Var(ix)
        x_Var(im+ix) = - x_Var(im+1-ix)
      end do

    end subroutine BoundaryAsym_x
!--------------------------------------------------------------------
    subroutine BoundarySym_p(p_Var)
      ! 1 次元 (x 方向) 配列に対称境界条件を適用する.

      real(DBKIND),intent(inout) :: p_Var(imin:imax) ! 入出力配列 
      integer                    :: ix               ! ループ添字

      ! 対称境界条件を適用する
      ! 
      !   ex.) im=5, xmargin=2 の場合 (imin=-1, imax=7)
      !
      !   p    -1   0   1   2   3   4   5   6   7 
      !     |-:-|-:-|-:-|-:-|-:-|-:-|-:-|-:-|-:-|
      !   x  -1   0   1   2   3   4   5   6   7
      !     <------->                   <------->  
      !    p_Var(imin:-1)    と     p_Var(im+1:imax) の値を更新
      !     
      !   p_Var(-1) = x_Var(1)
      !   p_Var(6)  = x_Var(4)
      !   p_Var(7)  = x_Var(3)
      !
      do ix = 1, xmargin-1
        p_Var(-ix)   = p_Var(ix)      
      end do

      do ix = 1, xmargin
        p_Var(im+ix) = p_Var(im+1-ix)
      end do

    end subroutine BoundarySym_p
!--------------------------------------------------------------------
    subroutine BoundaryAsym_p(p_Var)
      ! 1 次元 (x 方向) 配列に反対称境界条件を適用する.

      real(DBKIND),intent(inout) :: p_Var(imin:imax) ! 入出力配列 
      integer           :: ix               ! ループ添字

      ! 反対称境界条件を適用する
      ! 
      !   ex.) im=5, xmargin=2 の場合 (imin=-1, imax=7)
      !
      !   p    -1   0   1   2   3   4   5   6   7 
      !     |-:-|-:-|-:-|-:-|-:-|-:-|-:-|-:-|-:-|
      !   x  -1   0   1   2   3   4   5   6   7
      !     <------->                   <------->  
      !    p_Var(imin:0)     と      p_Var(im,imax) の値を更新
      !     
      !   x_Var(0)  = 0
      !   x_Var(-1) = - x_Var(1)
      !   x_Var(5)  = 0
      !   x_Var(6)  = - x_Var(4)
      !   x_Var(7)  = - x_Var(3)
      !
      p_Var(0) = 0.0d0
      p_Var(im) = 0.0d0
          
      do ix = 1, xmargin-1
        p_Var(-ix) = - p_Var(ix)
      end do

      do ix = 1, xmargin
        p_Var(im+ix) = - p_Var(im-ix)
      end do

    end subroutine BoundaryAsym_p
!--------------------------------------------------------------------
    subroutine BoundaryCyc(Var)
      ! 1 次元 (x 方向) 配列に周期境界条件を適用する.

      real(DBKIND),intent(inout) :: Var(imin:imax) ! 入出力配列 
      integer                    :: ix             ! ループ添字

      ! 周期界条件を適用する
      ! 
      !   ex.) im=5, xmargin=2 の場合 (imin=-1, imax=7)
      !
      !   p    -1   0   1   2   3   4   5   6   7 
      !     |-:-|-:-|-:-|-:-|-:-|-:-|-:-|-:-|-:-|
      !   x  -1   0   1   2   3   4   5   6   7
      !     <------->                   <------->  
      !    x_Var(imin:0)     と    x_Var(im+1,imax) の値を更新
      !    p_Var(imin:0)     と    p_Var(im+1,imax) の値を更新
      !     
      !   x_Var(0)  = x_Var(5)
      !   x_Var(-1) = x_Var(4)
      !   x_Var(6)  = x_Var(1)
      !   x_Var(7)  = x_Var(2)
      !     
      !   p_Var(0)  = p_Var(5)
      !   p_Var(-1) = p_Var(4)
      !   p_Var(6)  = p_Var(1)
      !   p_Var(7)  = p_Var(2)
      !
      do ix = 1, xmargin
        Var(1-ix)  = Var(im+1-ix)
        Var(im+ix) = Var(ix)
      end do

    end subroutine BoundaryCyc
!--------------------------------------------------------------------
end module x_bc_module
