!c Description:
!c   気相の比熱, 比熱の積分値, 比熱/温度の積分値 の計算
!c   SSL II の INSPL ルーチンから求めた比熱の補間係数を利用する
!c
!c Current Code Owner: 
!c   sugiyama@gfd-dennou.org
!c
!c Histry: 
!c   Version    Date          Comment
!c   -------    ----------    --------
!c   1.0        2003-02-05    作成
!c
!c Copyright (C) SUGIYAMA Ko-ichiro, 2003, All rights reserved

module interface_cp_spl
  interface

     subroutine cp_spl(temp, property, cp, cp_int, cp_dvt_int)  
       use prm_type, only: type_property
       real(8), intent(in)             :: temp       !温度
       real(8), intent(out), optional  :: cp         !比熱
       real(8), intent(out), optional  :: cp_int     !比熱の積分
       real(8), intent(out), optional  :: cp_dvt_int !比熱/温度の積分
       type(type_property), intent(in) :: property   !スプライン補間係数
     end subroutine cp_spl

  end interface
end module interface_cp_spl



subroutine cp_spl(temp, property, cp, cp_int, cp_dvt_int)  
  use prm_type, only: type_property, type_spl
  use prm_phys, only: temp_ref
  use interface_spl
  use interface_list_output
  use interface_list_get

  implicit none
  real(8), intent(in)             :: temp       !温度
  real(8), intent(out), optional  :: cp         !比熱
  real(8), intent(out), optional  :: cp_int     !比熱の積分
  real(8), intent(out), optional  :: cp_dvt_int !比熱/温度の積分
  type(type_property), intent(in) :: property   !スプライン補間係数
  
  real(8)                         :: t0       !積分開始温度
  real(8)                         :: t1       !積分終了温度
  real(8), allocatable            :: temp_dat(:)
  real(8), allocatable            :: dat_int(:) 
  real(8), allocatable            :: dat_dvt_int(:)
  integer                         :: N        !比熱データ配列で値をもつデータ数
  integer                         :: N_dat    !入力された温度をはさむデータ番号
  integer                         :: N_ref    !標準温度のデータ番号
  logical                         :: sw       
  type(type_spl)                  :: object   !スプライン補間係数


!!!
!!!データ点の番号を求める
!!!
  !リストから温度情報を取り出す
  call list_output(property%spl, temp=temp_dat, &
       & dat_int=dat_int, dat_dvt_int=dat_dvt_int)
  
  !配列のうち値をもつデータ数を求める. 
  N = size(temp_dat, 1)
  
  !入力された温度をはさむデータ点の番号を求める
  !データ点の温度 < 温度なデータ点番号のうち最も大きい番号を得る
  N_dat = maxloc(temp_dat, 1, temp_dat <= temp)
  
  !温度がデータ点の範囲に無い場合の扱い
  if (temp_dat(1) >= temp) N_dat = 1
  if (temp_dat(N) < temp)  N_dat = N
  
  !標準温度のデータ点を得る
  N_ref = maxloc(temp_dat, 1, temp_dat == temp_ref)
  
  !積分区間の準備
  t0 = temp_dat(N_dat)
  t1 = temp
  sw = temp_dat(1) <= temp .AND. temp <= temp_dat(N)

  !スタックを取得
  call list_get(temp_dat(N_dat), property%spl, object)
  
  
!!!
!!!比熱求める. SSL II の spline 補間を用いる
!!!温度が与えられた cp の温度範囲内にあるかどうかで補間式が異なる  
!!!
  if (present(cp)) then 
     call spl(object, t0, t1, sw, var=cp)
  end if
  
!!!
!!!T_i から T まで比熱を積分する. SSL II の spline 補間を用いる
!!!
  if (present(cp_int)) then 
     call spl(object, t0, t1, sw, var_int=cp_int)

     !標準温度からの積分値に変換. N_dat==N_ref ならばそのまま
     if (N_dat < N_ref) then 
        cp_int = - sum(dat_int(N_dat: N_ref-1)) + cp_int
     elseif (N_dat > N_ref) then 
        cp_int = sum(dat_int(N_ref: N_dat-1)) + cp_int
     end if
  end if

!!!
!!!T_i から T まで 比熱/温度 を積分する. SSL II の spline 補間を用いる. 
!!!
  if (present(cp_dvt_int)) then 
     call spl(object, t0, t1, sw, var_dvt_int=cp_dvt_int)
     
     !標準温度からの積分値に変換. N_dat==N_ref ならばそのまま
     if (N_dat < N_ref) then 
        cp_dvt_int = - sum(dat_dvt_int(N_dat: N_ref-1)) + cp_dvt_int
     elseif (N_dat > N_ref) then 
        cp_dvt_int = sum(dat_dvt_int(N_ref: N_dat-1)) + cp_dvt_int
     end if
  end if


!!!
!!!後かたづけ
!!!
  deallocate(temp_dat, dat_int, dat_dvt_int)

end subroutine cp_spl


