!---------------------------------------------------------------------
!     Copyright (C) GFD Dennou Club, 2004. All rights reserved.
!---------------------------------------------------------------------
                                                                 !=begin
!= Module GridSet
!
!   * Developer: SUGIYAMA Ko-ichiro (sugiyama@gfd-dennou.org)
!   * Version: $Id: gridset.f90,v 1.2.2.1 2005/10/06 07:58:34 kitamo Exp $ 
!   * Tag Name: $Name:  $
!   * Change History: 
!
!== Overview 
!
!座標軸設定用モジュール
!
!== Error Handling
!
!== Known Bugs
!
!== Note
!
!== Future Plans
!
                                                                 !=end

module gridset
  !--- 暗黙の型宣言禁止
  implicit none

  !--- save 属性
  save
                                                                 !=begin
  !== Public Interface
  real(8)               :: Xmin, Xmax    ! x 座標の始点・終点
  real(8)               :: Zmin, Zmax    ! z 座標の始点・終点
  real(8)               :: DelX, DelZ    !格子間隔
  real(8)               :: DelXZ         !平均格子間隔(平均混合距離)
  integer               :: NX, NZ        !格子点数
  integer               :: DimXMin       ! x 方向の配列添字の下限
  integer               :: DimXMax       ! x 方向の配列添字の上限
  integer               :: DimZMin       ! z 方向の配列添字の下限
  integer               :: DimZMax       ! z 方向の配列添字の上限
  integer               :: RegXMin       ! x 方向の物理領域を表す配列添字の下限
  integer               :: RegXMax       ! x 方向の物理領域を表す配列添字の上限
  integer               :: RegZMin       ! z 方向の物理領域を表す配列添字の下限
  integer               :: RegZMax       ! z 方向の物理領域を表す配列添字の上限
  integer               :: FileNX        !ファイル出力用
  integer               :: FileNZ        !ファイル出力用
  integer               :: FileXMin      !ファイル出力用
  integer               :: FileXMax      !ファイル出力用
  integer               :: FileZMin      !ファイル出力用
  integer               :: FileZMax      !ファイル出力用
  integer, parameter    :: Margin = 5    !境界のグリッド数
  integer, parameter    :: kind = 8      !精度を表す
  real(8), allocatable  :: s_X(:)        !X 座標軸(スカラー)
  real(8), allocatable  :: f_X(:)        !X 座標軸(ベクトル)
  real(8), allocatable  :: s_Z(:)        !Z 座標軸(スカラー)
  real(8), allocatable  :: f_Z(:)        !Z 座標軸(ベクトル)
                                                                 !=end  
contains
                                                                 !=begin
  !== Procedure Interface 
  !
  !=== Initialize module and acquire NAMELIST
  !
  !NAMELIST から情報を得て, 格子点を計算する
  !
  subroutine gridset_init(cfgfile)

    !=== Dependency
    use dc_trace,  only: BeginSub, EndSub 
    use debugset,  only: DebugOn 

    !=== Input
    character(*), intent(in) :: cfgfile
                                                                 !=end    
    !=== 内部変数の定義
    integer            :: i, k
                                                                 !=begin    
    !=== NAMELIST 
    NAMELIST /gridset/ &
         & NX, NZ, Xmin, Xmax, Zmin, Zmax
                                                                 !=end

    call BeginSub("gridset_init", &
&                 fmt="%c",       &
&                 c1="Initialize grid point and interval. ")
    
    open (10, FILE=cfgfile)
    read(10, NML=gridset)
    close(10)

    !==== 格子点間隔計算
    DelX = (Xmax - Xmin) / real(NX, kind)
    DelZ = (Zmax - Zmin) / real(NZ, kind)

    !==== 平均格子点間隔
    DelXZ = sqrt( DelX * DelZ )
    
    !==== 物理的に意味のある領域の上限・下限を決める
    RegXMin = 0
    RegXMax = NX
    RegZMin = 0
    RegZMax = NZ

    !==== 配列の上限・下限を決める
    DimXMin = RegXMin - Margin
    DimXMax = RegXMax + Margin
    DimZMin = RegZMin - Margin
    DimZMax = RegZMax + Margin

    !==== グリッドの設定
    allocate( f_X(DimXMin:DimXMax), f_Z(DimZMin:DimZMax) )
    do i = DimXMin, DimXMax
       f_X(i) = Xmin + DelX * ( real(i, kind) - RegXMin )
    end do
    do k = DimZMin, DimZMax
       f_Z(k) = Zmin + DelZ * ( real(k, kind) - RegZMin )
    end do
    
    !==== 半格子ずれたグリッドの設定. 等間隔を前提にしている.
    allocate( s_X(DimXMin: DimXMax), s_Z(DimZMin: DimZMax) )
    s_X(DimXMin+1:DimXMax) =            &
         &  (                     &
         &     f_X(DimXMin+1:DimXMax)     &
         &   + f_X(DimXMin:DimXMax-1)     &
         &  ) * 5.0d-1
    s_X(DimXMin) = s_X(DimXMin+1) - DelX
    
    s_Z(DimZMin+1:DimZMax) =             &
         &  (                     &
         &     f_Z(DimZMin+1:DimZMax)     &
         &   + f_Z(DimZMin:DimZMax-1)     &
         &  ) * 5.0d-1
    s_Z(DimZMin) = s_Z(DimZMin+1) - DelZ

    !==== デバッグモードか否かで, ファイル出力に用いる変数の大きさを変える
    if (DebugOn) then
       FileNX   = size(f_X, 1)
       FileNZ   = size(f_Z, 1)
       FileXMin = DimXMin
       FileXMax = DimXMax
       FileZMin = DimZMin
       FileZMax = DimZMax
    else
       FileNX   = NX
       FileNZ   = NZ
       FileXMin = RegXMin + 1
       FileXMax = RegXMax
       FileZMin = RegZMin + 1
       FileZMax = RegZMax
    end if
    
    !==== 確認
!    write(*,*) "Xmin, Xmax", Xmin, Xmax
!    write(*,*) "Zmin, Zmax", Zmin, Zmax
!    write(*,*) "DelX, DelZ", DelX, DelZ
!    write(*,*) "DelXZ", DelXZ
!    write(*,*) "NX, NZ", NX, NZ
!    write(*,*) "DimXMin, DimXMax", DimXMin, DimXMax
!    write(*,*) "DimZMin, DimZMax", DimZMin, DimZMax
!    write(*,*) "RegXMin, RegXMax", RegXMin, RegXMax
!    write(*,*) "RegZMin, RegZMax", RegZMin, RegZMax
!    write(*,*) "FileNX, FileNZ", FileNX, FileNZ
!    write(*,*) "FileXMin, FileXMax", FileXMin, FileXMax
!    write(*,*) "FileZMin, FileZMax", FileZMin, FileZMax
!    write(*,*) "Margin", Margin
!    write(*,*) "kind", kind
!    write(*,*) "s_X", s_X
!    write(*,*) "f_X", f_X
!    write(*,*) "s_Z", s_Z
!    write(*,*) "f_Z", f_Z

    call EndSub("gridset_init")

  end subroutine gridset_init
  
end module gridset
