!= 3 次元 (xyz 方向) 不等間隔交互格子 微分演算モジュール
!
!* 履歴
!  * 2007/07/15 (小高正嗣) : 3D deepconv へ移植, dc_types を Use.
!  * 2007/06/27 (小高正嗣) : 1 次元微分演算モジュールに依存しないよう修正
!  * 2006/06/07 (小高正嗣) : 新規作成
!

module xyz_deriv_module
  != 3 次元 (xyz 方向) 不等間隔交互格子 微分演算モジュール
  !
  !== 機能
  !
  ! xyz_deriv_module は, 3 次元 (xyz 方向) 不等間隔交互格子を用いた有限差分
  ! 法に基づく数値モデルのための, 微分演算を行う Fortran90 関数を提供する. 
  ! 微分演算は 2 次精度中心差分を用いて行う.
  !
  ! このモジュールは下請けモジュールとして xyz_base_module, data_type 
  ! モジュールを用いている. 
  !
  ! モジュール内の変数と手続きの命名方法については xyz_module を参照のこと.
  !
  !
  !== 変数, 手続きの要約
  !
  !=== 1 階微分
  !
  ! xyz_dx_pyz, pyz_dx_xyz :: x 方向 1 階微分を計算する
  ! xyz_dy_xqz, xqz_dy_xyz :: y 方向 1 階微分を計算する
  ! xyz_dz_xyr, xyr_dz_xyz :: z 方向 1 階微分を計算する
  !

  use dc_types,        only : DBKIND => DP
  use x_base_module, only: imin, imax
  use y_base_module, only: jmin, jmax
  use z_base_module, only: kmin, kmax
!  use xyz_base_module, only : imin, imax, jmin, jmax, kmin, kmax, &
!    &                         x_dx, p_dx, y_dy, q_dy, z_dz, r_dz       
  use xyz_base_module, only : x_dx, p_dx, y_dy, q_dy, z_dz, r_dz       

  implicit none
  private
  public :: xyz_dx_pyz, pyz_dx_xyz, &
    &       xyz_dy_xqz, xqz_dy_xyz, &
    &       xyz_dz_xyr, xyr_dz_xyz

  public :: pqz_dx_xqz, xqz_dx_pqz, &
    &       pyr_dx_xyr, xyr_dx_pyr, &
    &       pqz_dy_pyz, pyz_dy_pqz, &
    &       xqr_dy_xyr, xyr_dy_xqr, &
    &       xqr_dz_xqz, xqz_dz_xqr, &
    &       pyr_dz_pyz, pyz_dz_pyr

 
  contains
!--------------------------------------------------------------------
    function xyz_dx_pyz(pyz_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: pyz_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: xyz_dx_pyz(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: ix

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      xyz_dx_pyz = 0.0d0

      ! 1 階微分の計算
      !
      do ix = imin+1, imax
        xyz_dx_pyz(ix,:,:) = (pyz_Var(ix,:,:)-pyz_Var(ix-1,:,:))/x_dx(ix)
      end do

    end function xyz_dx_pyz
!--------------------------------------------------------------------
    function pyz_dx_xyz(xyz_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: xyz_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: pyz_dx_xyz(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: ix 

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      pyz_dx_xyz = 0.0d0

      ! 1 階微分の計算
      !
      do ix = imin, imax-1
        pyz_dx_xyz(ix,:,:) = (xyz_Var(ix+1,:,:) - xyz_Var(ix,:,:))/p_dx(ix)
      end do

    end function pyz_dx_xyz
!--------------------------------------------------------------------
    function pqz_dx_xqz(xqz_Var)
  
      real(DBKIND),intent(in) :: xqz_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: pqz_dx_xqz(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: ix

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      pqz_dx_xqz = 0.0d0

      ! 1 階微分の計算
      !
      do ix = imin, imax-1
        pqz_dx_xqz(ix,:,:) = (xqz_Var(ix+1,:,:)-xqz_Var(ix,:,:))/p_dx(ix)
      end do

    end function pqz_dx_xqz
!--------------------------------------------------------------------
    function xqz_dx_pqz(pqz_Var)
  
      real(DBKIND),intent(in) :: pqz_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: xqz_dx_pqz(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: ix

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      xqz_dx_pqz = 0.0d0

      ! 1 階微分の計算
      !
      do ix = imin+1, imax
        xqz_dx_pqz(ix,:,:) = (pqz_Var(ix,:,:)-pqz_Var(ix-1,:,:))/x_dx(ix)
      end do

    end function xqz_dx_pqz
!--------------------------------------------------------------------
    function pyr_dx_xyr(xyr_Var)
  
      real(DBKIND),intent(in) :: xyr_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: pyr_dx_xyr(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: ix

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      pyr_dx_xyr = 0.0d0

      ! 1 階微分の計算
      !
      do ix = imin, imax-1
        pyr_dx_xyr(ix,:,:) = (xyr_Var(ix+1,:,:)-xyr_Var(ix,:,:))/p_dx(ix)
      end do

    end function pyr_dx_xyr
!--------------------------------------------------------------------
    function xyr_dx_pyr(pyr_Var)
  
      real(DBKIND),intent(in) :: pyr_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: xyr_dx_pyr(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: ix

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      xyr_dx_pyr = 0.0d0

      ! 1 階微分の計算
      !
      do ix = imin+1, imax
        xyr_dx_pyr(ix,:,:) = (pyr_Var(ix,:,:)-pyr_Var(ix-1,:,:))/x_dx(ix)
      end do

    end function xyr_dx_pyr
!--------------------------------------------------------------------
    function xyz_dy_xqz(xqz_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: xqz_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: xyz_dy_xqz(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: jy 

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      xyz_dy_xqz = 0.0d0

      ! 1 階微分の計算
      !
      do jy = jmin+1, jmax
        xyz_dy_xqz(:,jy,:) = (xqz_Var(:,jy,:) - xqz_Var(:,jy-1,:))/y_dy(jy)
      end do

    end function xyz_dy_xqz
!--------------------------------------------------------------------
    function xqz_dy_xyz(xyz_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: xyz_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: xqz_dy_xyz(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: jy

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      xqz_dy_xyz = 0.0d0

      ! 1 階微分の計算
      !
      do jy = jmin, jmax
          xqz_dy_xyz(:,jy,:) = (xyz_Var(:,jy+1,:) - xyz_Var(:,jy,:))/q_dy(jy)
      end do

    end function xqz_dy_xyz
!--------------------------------------------------------------------
    function pqz_dy_pyz(pyz_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: pyz_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: pqz_dy_pyz(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: jy

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      pqz_dy_pyz = 0.0d0

      ! 1 階微分の計算
      !
      do jy = jmin, jmax
          pqz_dy_pyz(:,jy,:) = (pyz_Var(:,jy+1,:) - pyz_Var(:,jy,:))/q_dy(jy)
      end do

    end function pqz_dy_pyz
!--------------------------------------------------------------------
    function pyz_dy_pqz(pqz_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: pqz_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: pyz_dy_pqz(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: jy 

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      pyz_dy_pqz = 0.0d0

      ! 1 階微分の計算
      !
      do jy = jmin+1, jmax
        pyz_dy_pqz(:,jy,:) = (pqz_Var(:,jy,:) - pqz_Var(:,jy-1,:))/y_dy(jy)
      end do

    end function pyz_dy_pqz
!--------------------------------------------------------------------
    function xqr_dy_xyr(xyr_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: xyr_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: xqr_dy_xyr(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: jy

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      xqr_dy_xyr = 0.0d0

      ! 1 階微分の計算
      !
      do jy = jmin, jmax
          xqr_dy_xyr(:,jy,:) = (xyr_Var(:,jy+1,:) - xyr_Var(:,jy,:))/q_dy(jy)
      end do

    end function xqr_dy_xyr
!--------------------------------------------------------------------
    function xyr_dy_xqr(xqr_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: xqr_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: xyr_dy_xqr(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: jy 

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      xyr_dy_xqr = 0.0d0

      ! 1 階微分の計算
      !
      do jy = jmin+1, jmax
        xyr_dy_xqr(:,jy,:) = (xqr_Var(:,jy,:) - xqr_Var(:,jy-1,:))/y_dy(jy)
      end do

    end function xyr_dy_xqr
!--------------------------------------------------------------------
    function xyz_dz_xyr(xyr_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: xyr_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: xyz_dz_xyr(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: kz

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      xyz_dz_xyr = 0.0d0

      ! 1 階微分の計算
      !
      do kz = kmin+1, kmax
        xyz_dz_xyr(:,:,kz) = (xyr_Var(:,:,kz) - xyr_Var(:,:,kz-1))/z_dz(kz)
      end do

    end function xyz_dz_xyr
!--------------------------------------------------------------------
    function xyr_dz_xyz(xyz_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: xyz_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: xyr_dz_xyz(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: kz

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      xyr_dz_xyz = 0.0d0

      ! 1 階微分の計算
      !
      do kz = kmin, kmax-1
        xyr_dz_xyz(:,:,kz) = (xyz_Var(:,:,kz+1) - xyz_Var(:,:,kz))/r_dz(kz)
      end do

    end function xyr_dz_xyz
!--------------------------------------------------------------------
    function pyr_dz_pyz(pyz_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: pyz_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: pyr_dz_pyz(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: kz

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      pyr_dz_pyz = 0.0d0

      ! 1 階微分の計算
      !
      do kz = kmin, kmax-1
        pyr_dz_pyz(:,:,kz) = (pyz_Var(:,:,kz+1) - pyz_Var(:,:,kz))/r_dz(kz)
      end do

    end function pyr_dz_pyz
!--------------------------------------------------------------------
    function pyz_dz_pyr(pyr_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: pyr_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: pyz_dz_pyr(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: kz

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      pyz_dz_pyr = 0.0d0

      ! 1 階微分の計算
      !
      do kz = kmin+1, kmax
        pyz_dz_pyr(:,:,kz) = (pyr_Var(:,:,kz) - pyr_Var(:,:,kz-1))/z_dz(kz)
      end do

    end function pyz_dz_pyr
!--------------------------------------------------------------------
    function xqr_dz_xqz(xqz_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: xqz_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: xqr_dz_xqz(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: kz

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      xqr_dz_xqz = 0.0d0

      ! 1 階微分の計算
      !
      do kz = kmin, kmax-1
        xqr_dz_xqz(:,:,kz) = (xqz_Var(:,:,kz+1) - xqz_Var(:,:,kz))/r_dz(kz)
      end do

    end function xqr_dz_xqz
!--------------------------------------------------------------------
    function xqz_dz_xqr(xqr_Var)
      ! 半整数格子点上の 1 階微分を計算する
  
      real(DBKIND),intent(in) :: xqr_Var(imin:imax,jmin:jmax,kmin:kmax) 
      real(DBKIND)            :: xqz_dz_xqr(imin:imax,jmin:jmax,kmin:kmax)
      integer                 :: kz

      ! 初期化
      ! * 0 割りを防ぐためにはマシンイプシロン値を用いるべき
      !
      xqz_dz_xqr = 0.0d0

      ! 1 階微分の計算
      !
      do kz = kmin+1, kmax
        xqz_dz_xqr(:,:,kz) = (xqr_Var(:,:,kz) - xqr_Var(:,:,kz-1))/z_dz(kz)
      end do

    end function xqz_dz_xqr
!--------------------------------------------------------------------
end module xyz_deriv_module
