!---------------------------------------------------------------------
!     Copyright (C) GFD Dennou Club, 2004, 2006. All rights reserved.
!---------------------------------------------------------------------
!= Module Differentiate_Center2
!
!   * Developer: SUGIYAMA Ko-ichiro
!   * Version: $Id: differentiate_center2.f90,v 1.2 2005/04/22 15:01:52 sugiyama Exp $ 
!   * Tag Name: $Name:  $
!   * Change History: 
!
!== Overview 
!
!2 次精度の微分演算を行うための関数群をまとめたパッケージ型モジュール
!水平 Arakawa-C, 鉛直 Lorentz グリッドでの微分計算
!
!== Error Handling
!
!== Known Bugs
!
!== Note
!
!基本的に DelX もしくは DelZ 離れた格子点位置での微分しか定義していない. 
!格子点 2 個分, 4 個分離れた格子点位置の値を使うような微分は, 
!明らかに精度が落ちるためである. 
!
!== Future Plans
!

module differentiate_center2
  !
  !2 次精度の微分演算を行うための関数群をまとめたパッケージ型モジュール
  !水平 Arakawa-C, 鉛直 Lorentz グリッドでの微分計算
  !

  !モジュール読み込み
  use gridset,    only: DimXMin,  &! 配列の X 方向の下限
    &                   DimXMax,  &! 配列の X 方向の上限
    &                   DimZMin,  &! 配列の Z 方向の下限
    &                   DimZMax,  &! 配列の Z 方向の上限
    &                   DelX,     &! X 方向の格子点間隔
    &                   DelZ       ! Z 方向の格子点間隔

  !暗黙の型宣言禁止
  implicit none

  !private 属性
  private

  !公開要素
  public xz_dx_pz
  public xz_dz_xr
  public pz_dx_xz
  public pz_dz_pr
  public xr_dx_pr
  public xr_dz_xz
  public pr_dz_pz
  public pr_dx_xr

contains 

!!!---------------------------------------------------------------------
  function xz_dx_pz( pz_var ) 
    !
    ! x, z 方向に半格子ずれた点での x 方向 2 次精度微分演算
    !

    !暗黙の型宣言禁止
    implicit none

    !変数定義
    real(8), intent(in) :: pz_var(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分演算の対象となる変数
    real(8)             :: xz_dx_pz(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分値
    
    xz_dx_pz = 0.0d0 
    xz_dx_pz(DimXMin+1 : DimXMax, DimZMin : DimZMax) =        &
      &  (                                                    &
      &     pz_var(DimXMin+1 : DimXMax, DimZMin : DimZMax)    &
      &   - pz_var(DimXMin   : DimXMax-1, DimZMin : DimZMax)  &
      &  ) / DelX

  end function xz_dx_pz


!!!---------------------------------------------------------------------
  function xz_dz_xr(xr_var) 
    !
    ! x, z 方向に半格子ずれた点での z 方向 2 次精度微分演算
    !

    !暗黙の型宣言禁止
    implicit none

    !変数定義
    real(8), intent(in) :: xr_var(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分演算の対象となる変数
    real(8)             :: xz_dz_xr(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分値
    
    xz_dz_xr = 0.0d0 
    xz_dz_xr(DimXMin:DimXMax,DimZMin+1:DimZMax) =         &
      &  (                                                &
      &     xr_var(DimXMin:DimXMax,DimZMin+1:DimZMax)     &
      &   - xr_var(DimXMin:DimXMax,DimZMin:DimZMax-1)     &
      &  ) / DelZ

  end function xz_dz_xr


!!!---------------------------------------------------------------------
  function pz_dx_xz( xz_var ) 
    !
    ! z 方向に半格子ずれた点での x 方向 2 次精度微分演算
    !

    !暗黙の型宣言禁止
    implicit none

    !変数定義    
    real(8), intent(in) :: xz_var(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分演算の対象となる変数
    real(8)             :: pz_dx_xz(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分値    

    pz_dx_xz = 0.0d0
    pz_dx_xz(DimXMin:DimXMax-1,DimZMin:DimZMax) =         &
      &  (                                                &
      &     xz_var(DimXMin+1:DimXMax,DimZMin:DimZMax)     &
      &   - xz_var(DimXMin:DimXMax-1,DimZMin:DimZMax)     &
      &  ) / DelX

  end function pz_dx_xz
  

!!!---------------------------------------------------------------------
  function pz_dz_pr( pr_var ) 
    !
    ! z 方向に半格子ずれた点での z 方向 2 次精度微分演算
    !

    !暗黙の型宣言禁止
    implicit none
  
    real(8), intent(in) :: pr_var(DimXMin:DimXMax, DimZMin:DimZMax)
    real(8)             :: pz_dz_pr(DimXMin:DimXMax, DimZMin:DimZMax)
    
    pz_dz_pr = 0.0d0 
    pz_dz_pr(DimXMin:DimXMax,DimZMin+1:DimZMax) =       & 
      &  (                                              &
      &      pr_var(DimXMin:DimXMax,DimZMin+1:DimZMax)  &
      &   -  pr_var(DimXMin:DimXMax,DimZMin:DimZMax-1)  &
      &  ) / DelZ

  end function pz_dz_pr
  

!!!---------------------------------------------------------------------  
  function xr_dx_pr( pr_var ) 
    !
    ! x 方向に半格子ずれた点での x 方向 2 次精度微分演算
    !

    !暗黙の型宣言禁止
    implicit none

    !変数定義
    real(8), intent(in) :: pr_var(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分演算の対象となる変数
    real(8)             :: xr_dx_pr(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分値    

    xr_dx_pr = 0.0d0 
    xr_dx_pr(DimXMin+1:DimXMax,DimZMin:DimZMax) =        & 
      &  (                                               &
      &      pr_var(DimXMin+1:DimXMax,DimZMin:DimZMax)   &
      &   -  pr_var(DimXMin:DimXMax-1,DimZMin:DimZMax)   &
      &  ) / DelX

  end function xr_dx_pr
  

!!!---------------------------------------------------------------------  
  function xr_dz_xz( xz_var ) 
    !
    ! x 方向に半格子ずれた点での z 方向 2 次精度微分演算
    !

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

    !変数定義
    real(8), intent(in) :: xz_var(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分演算の対象となる変数
    real(8)             :: xr_dz_xz(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分値

    xr_dz_xz = 0.0d0 
    xr_dz_xz(DimXMin:DimXMax,DimZMin:DimZMax-1) =         &
      &  (                                                &
      &     xz_var(DimXMin:DimXMax,DimZMin+1:DimZMax)     &
      &   - xz_var(DimXMin:DimXMax,DimZMin:DimZMax-1)     &
      &  ) / DelZ

  end function xr_dz_xz


!!!---------------------------------------------------------------------  
  function pr_dx_xr( xr_var ) 
    !
    ! 格子点上での x 方向 2 次精度微分演算
    !

    !暗黙の型宣言禁止
    implicit none

    !変数定義
    real(8), intent(in) :: xr_var(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分演算の対象となる変数
    real(8)             :: pr_dx_xr(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分値
    
    pr_dx_xr = 0.0d0 
    pr_dx_xr(DimXMin:DimXMax-1,DimZMin:DimZMax) =        & 
      &  (                                               &
      &      xr_var(DimXMin+1:DimXMax,DimZMin:DimZMax)   &
      &   -  xr_var(DimXMin:DimXMax-1,DimZMin:DimZMax)   &
      &  ) / DelX

  end function pr_dx_xr
  

!!!---------------------------------------------------------------------  
  function pr_dz_pz( pz_var ) 
    !
    ! 格子点上での z 方向 2 次精度微分演算
    !

    !暗黙の型宣言禁止
    implicit none
    
    !変数定義
    real(8), intent(in) :: pz_var(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分演算の対象となる変数
    real(8)             :: pr_dz_pz(DimXMin:DimXMax, DimZMin:DimZMax)
                                     !微分値    

    pr_dz_pz = 0.0d0 
    pr_dz_pz(DimXMin:DimXMax,DimZMin:DimZMax-1) =    & 
      &  (                                           &
      &      pz_var(DimXMin:DimXMax,DimZMin+1:DimZMax)  &
      &   -  pz_var(DimXMin:DimXMax,DimZMin:DimZMax-1)  &
      &  ) / DelZ

  end function pr_dz_pz
  
end module differentiate_center2
