!---------------------------------------------------------------------
!     Copyright (C) GFD Dennou Club, 2004. All rights reserved.
!---------------------------------------------------------------------
!= Module ChemBook
!
!   * Developer: SUGIYAMA Ko-ichiro (sugiyama@gfd-dennou.org)
!   * Version: $Id: chemset.f90,v 1.2 2005/04/22 15:01:52 sugiyama Exp $ 
!   * Tag Name: $Name:  $
!   * Change History: 
!
!== Overview 
!
!諸々の化学種の物性データを保管するモジュール
!   * 分子量
!   * 比熱 
!   * Antoine の式の係数
!   * 
!
!== Error Handling
!
!== Known Bugs
!
!== Note
!
!   * 原子番号は 20 までしか定義していない. 
!   * 分子はよく出てくるものしか定義していない. 
!   * 分子は主要元素 7 つから成るものとする. (H, He, C, N, O, S)
!
!== References
!
!   * 元素の質量は化学便覧改訂 4 版(丸善)より
!
!== Future Plans
!


module ChemDataBase
  save

  !変数一覧
  integer, parameter :: ChemData_SpcNum = 5
  integer, parameter :: ChemData_AtmNum = 6
  real(8)            :: ChemData_AtmWt(ChemData_AtmNum)  !原子量 [kg/mol]
  real(8)            :: ChemData_MolWt(ChemData_SpcNum)  !分子量 [kg/mol]
  real(8)            :: ChemData_CpPerMol(ChemData_SpcNum)    
                                                     !比熱(モル当量) [J/K mol]
  real(8)            :: ChemData_CpPerMass(ChemData_SpcNum) 
                                                     !比熱(単位質量) [J/K kg]
  real(8)            :: ChemData_Entropy(ChemData_SpcNum)  
                                                     !基準エントロピー[J/K mol]
  real(8)            :: ChemData_Enthalpy(ChemData_SpcNum)
                                                     !基準エンタルピー[J/K mol]
  real(8)            :: ChemData_SVapPress_Antoine(ChemData_SpcNum,3) 
                                                     !Antoine 式の係数
  integer            :: ChemData_SpcForm(ChemData_SpcNum,ChemData_AtmNum) 
                                                     !分子を構成する元素の個数
  character(2)       :: ChemData_AtmSymbol(ChemData_AtmNum)   !原子記号
  character(10)      :: ChemData_SpcSymbol(ChemData_SpcNum)   !分子記号

contains

  subroutine ChemData_Init
    !
    ! 物質の名前に対して番号付けを行い, その番号に対して
    ! 諸々の物性値を割り当てる
    !

    !暗黙の型宣言禁止
    implicit none

    !内部変数
    integer   :: SNum, ANum1, ANum2

    !-------------------------------------------------------------
    ! 元素, 分子名を配列に格納. 
    !-------------------------------------------------------------
    !原子記号 
    ChemData_AtmSymbol = (/ "H ", "He", "C ", "N ", "O ", "S " /)

    !原子量 (kg/mol). 
    ChemData_AtmWt = (/                       &
      & 1.00794d-3,  4.002602d-3, 12.0107d-3, &
      & 14.00674d-3, 15.9994d-3,  32.066d-3 /) 

    !分子
    ChemData_SpcSymbol = (/         &
      & "N2-g ",  "O2-g ", "H2O-g",  "H2O-l", "H2O-s"  /)


    !-------------------------------------------------------------
    ! それぞれの元素, 分子に対応する物性値を格納
    !-------------------------------------------------------------
    !初期化
    ChemData_MolWt     = 0.0d0
    ChemData_CpPerMol  = 0.0d0
    ChemData_CpPerMass = 0.0d0
    ChemData_Entropy   = 0.0d0
    ChemData_Enthalpy  = 0.0d0
    ChemData_SpcForm   = 0.0d0
    ChemData_SVapPress_Antoine = 0.0d0
    
    !!=============================================================
    !! N2-g に関する物性
    !!=============================================================
    SNum  = ChemDataSearch( ChemData_SpcSymbol, 'N2-g')
    ANum1 = ChemDataSearch( ChemData_AtmSymbol, 'N')

    !分子を構成する元素
    ChemData_SpcForm(SNum,ANum1) = 2.0d0

    !分子量 [kg/mol]
    ChemData_MolWt(SNum) = dot_product(ChemData_AtmWt, ChemData_SpcForm(SNum,:))
    
    !比熱 [J/K mol]
    ChemData_CpPerMol(SNum) = 29.124d0

    !比熱 [J/K kg]
    ChemData_CpPerMass(SNum) = ChemData_CpPerMol(SNum) / ChemData_MolWt(SNum)

    !基準状態でのエントロピー 
    ChemData_Entropy(SNum) = 191.609d0

    !基準状態でのエンタルピー
    ChemData_Enthalpy(SNum) = 0.0d0


    !!=============================================================
    !! O2-g に関する物性
    !!=============================================================
    SNum  = ChemDataSearch( ChemData_SpcSymbol, 'O2-g')
    ANum1 = ChemDataSearch( ChemData_AtmSymbol, 'O')

    !分子を構成する元素
    ChemData_SpcForm(SNum,ANum1) = 2.0d0

    !分子量 [kg/mol]
    ChemData_MolWt(SNum) = dot_product(ChemData_AtmWt, ChemData_SpcForm(SNum,:))

    !比熱 [J/K mol]
    ChemData_CpPerMol(SNum) = 29.0d0
    
    !比熱 [J/K kg]
    ChemData_CpPerMass(SNum) = ChemData_CpPerMol(SNum) / ChemData_MolWt(SNum)

    !基準状態でのエントロピー 
    ChemData_Entropy(SNum) = 0.0d0
    
    !基準状態でのエンタルピー
    ChemData_Enthalpy(SNum) = 0.0d0


    !!=============================================================
    !! H2O-g に関する物性
    !!=============================================================
    SNum  = ChemDataSearch( ChemData_SpcSymbol, 'H2O-g')
    ANum1 = ChemDataSearch( ChemData_AtmSymbol, 'H')
    ANum2 = ChemDataSearch( ChemData_AtmSymbol, 'O')

    !分子を構成する元素
    ChemData_SpcForm(SNum,ANum1) = 2.0d0
    ChemData_SpcForm(SNum,ANum2) = 1.0d0

    !分子量 [kg/mol]
    ChemData_MolWt(SNum) = dot_product(ChemData_AtmWt, ChemData_SpcForm(SNum,:))

    !比熱 [J/K mol]
    ChemData_CpPerMol(SNum) = 33.59d0

    !比熱 [J/K kg]
    ChemData_CpPerMass(SNum) = ChemData_CpPerMol(SNum) / ChemData_MolWt(SNum)

    !基準状態でのエントロピー 
    ChemData_Entropy(SNum) = 188.834d0

    !基準状態でのエンタルピー
    ChemData_Enthalpy(SNum) = -2.41826d5

    !!=============================================================
    !! H2O-l に関する物性
    !!=============================================================
    SNum  = ChemDataSearch( ChemData_SpcSymbol, 'H2O-l')
    ANum1 = ChemDataSearch( ChemData_AtmSymbol, 'H')
    ANum2 = ChemDataSearch( ChemData_AtmSymbol, 'O')

    !分子を構成する元素
    ChemData_SpcForm(SNum,ANum1) = 2.0d0
    ChemData_SpcForm(SNum,ANum2) = 1.0d0

    !分子量 [kg/mol]
    ChemData_MolWt(SNum) = dot_product(ChemData_AtmWt, ChemData_SpcForm(SNum,:))

    !Antoine の式の係数
    ChemData_SvapPress_Antoine(SNum,1) =  7.9186968d0
    ChemData_SvapPress_Antoine(SNum,2) =  1636.909d0
    ChemData_SvapPress_Antoine(SNum,3) =  224.92d0


    !!=============================================================
    !! H2O-s に関する物性
    !!=============================================================
    SNum  = ChemDataSearch( ChemData_SpcSymbol, 'H2O-s')
    ANum1 = ChemDataSearch( ChemData_AtmSymbol, 'H')
    ANum2 = ChemDataSearch( ChemData_AtmSymbol, 'O')

    !分子を構成する元素
    ChemData_SpcForm(SNum,ANum1) = 2.0d0
    ChemData_SpcForm(SNum,ANum2) = 1.0d0

    !分子量 [kg/mol]
    ChemData_MolWt(SNum) = dot_product(ChemData_AtmWt, ChemData_SpcForm(SNum,:))

    !Antoine の式の係数
    ChemData_SvapPress_Antoine(SNum,1) =  8.184254d0
    ChemData_SvapPress_Antoine(SNum,2) =  1791.3d0
    ChemData_SvapPress_Antoine(SNum,3) =  238.1d0

  end subroutine ChemData_Init


  function ChemDataSearch( array, var)
    !
    ! 名前の検索エンジン
    !

    !暗黙の型宣言禁止
    implicit none

    !入出力変数
    integer                  :: ChemDataSearch
    character(*), intent(in) :: array(:)
    character(*), intent(in) :: var

    !内部変数
    integer                  :: i

    !探査
    Search: do i = 1, size(array,1)
      if (array(i) == var) then 
        ChemDataSearch = i
        exit Search
      end if
    end do Search
    
  end function ChemDataSearch
  

  function ChemData_SpcName( num, SpcSymbol )
    !
    ! 文字として与えられた化学種名から, その化学種の配列添え字を得る
    !

    !暗黙の型宣言禁止
    implicit none

    !入出力変数
    integer                  :: ChemData_SpcName(Num)
    integer, intent(in)      :: Num
    character(*), intent(in) :: SpcSymbol(:)

    !内部変数
    integer                  :: i, j

    !初期化
    ChemData_SpcName = 0.0d0

    !探査
    do i = 1, size(SpcSymbol,1)
      Search: do j = 1, size(ChemData_SpcSymbol,1)
        if (ChemData_SpcSymbol(j) == SpcSymbol(i)) then 
          ChemData_SpcName(i) = j
          exit Search
        end if
      end do Search
    end do

  end function ChemData_SpcName
  
end module ChemDataBase
