!
!>
!!
module SimParamList

  ! モジュール引用 ; Use statements
  !

  use, intrinsic :: iso_c_binding

  !* gtool ***********
  !*

  ! 種類型パラメータ
  ! kind type parameter
  !
  use dc_types, only: &
    & DP, TOKEN, STRING

  !* IGMBaseLib ***********
  !*

  ! C との相互利用のためのユーティリティ
  ! Utility for interoperability with C
  !
  use CBinding_Utility, only: &
    & c_f_string, f_c_string
    
  ! 宣言文 ; Declaration statements
  !
  implicit none
  private

  ! 公開手続き
  ! Public procedures
  !
  public :: read_simulation_parameters, readSimParams_And_SyncronizeCPPClass

  ! 非公開変数
  ! Private variables
  !

  ! * 格子設定に関するパラメータ
  !  Parameters associated with the configuration of the grid 
  !
  type, bind(C), public :: GridParam_List
  
    !> \~japanese
    !! \~english
    character(STRING) :: gridFile_path
  
    !> \~japanese (正二十面格子の)水平分割レベル. 
    !! \~english Horizontal division level of icosahedral grid. 
    integer :: glevel
  
    !> \~japanese
    !! \~english
    integer :: inthalf_VerticaldivLv_Num
  
  end type GridParam_List


  ! * 系の設定に関するパラメータ
  !  Parameters associated with the configuration of the system
  !
  type, bind(C) :: SystemParam_List  
    
    !> \~japanese 長いタイムステップ [s]. 
    !! \~english Large(Long) time step [s].   
    real(DP) :: planet_radius
  
    !> \~japanese モデル領域の上端高度 [m]. 
    !! \~english The top height of model domain [m]. 
    real(DP) :: domain_top
  
    !> \~japanese 自転角速度 [s^-1]. 
    !! \~english Angular velocity [s^-1]. 
    real(DP) :: Omega
  
    !> \~japanese 重力加速度. 
    !! \~english . 
    real(DP) :: Grav
  
    !> \~japanese 気体定数. 
    !! \~english Gas constant []. 
    real(DP) :: GasConst
  
    !> \~japanese 定圧比熱 []. 
    !! \~english  []. 
    real(DP) :: Cp
  
    !> \~japanese 定積比熱 []. 
    !! \~english  []. 
    real(DP) :: Cv
    
  end type SystemParam_List
    
  ! * 時間積分に関するパラメータ
  !  Parameters associated with temporal integration
  !
  type, bind(C), public :: TimeIntegParam_List

    !> \~japanese 短いタイムステップ [s]. 
    !! \~english Small(Short) time step [s].   
    real(DP) :: DelTimeShort
  
    !> \~japanese 長いタイムステップ [s]. 
    !! \~english Large(Long) time step [s]. 
    real(DP) :: DelTimeLong
  
    !> \~japanese 積分時間 [s]. 
    !! \~english Integeration time [s]. 
    real(DP) :: IntegTime
    
  end type TimeIntegParam_List
  
  !
  !
  !
  type, bind(C), public :: DataOutputParam_List

    real(DP) :: OutputTick
    real(DP) :: EnergyAnalysisOutputTick
    character(STRING) :: FieldzDataFilePath
    character(STRING) :: FieldrDataFilePath
!    character(STRING) :: BasicFieldDataFielPath
!    character(STRING) :: InitFieldDataFielPath   
  end type DataOutputParam_List
  
  ! 数値安定性のためのパラメータ
  ! Parameters for numerical stability
  !
  
  type, bind(C), public :: NumStabilityParam_List
    real(DP) :: alphaDash_dH
    real(DP) :: alpha_dH
    real(DP) :: alphaDash_dV
    real(DP) :: alpha_dV
    real(DP) :: gamma_h
    real(DP) :: K_H
    real(DP) :: gamma_v
    real(DP) :: K_V
  end type NumStabilityParam_List

  type(GridParam_List), public, target :: GridParamList
  type(SystemParam_List), public, target :: SystemParamList
  type(TimeIntegParam_List), public, target :: TimeIntegParamList
  type(DataOutputParam_List), public, target :: DataOutputParamList
  type(NumStabilityParam_List), public, target :: NumStabilityParamList

contains

subroutine read_simulation_parameters( &
  & nmlfile_name &
  & )
  ! 宣言文 ; Declaration statements
  !

  character(*), intent(in) :: nmlfile_name

  ! 作業変数
  ! Work variables
  !
  namelist /Grid_Params/ GridParamList

  namelist /System_Params/ SystemParamList

  namelist /TimeInteg_Params/ TimeIntegParamList
  
  namelist /DataOutput_Params/ DataOutputParamList
  
  namelist /NumStability_Params/ NumStabilityParamList
  
  integer, parameter :: deviceID = 10

  ! 実行文 ; Executable statements
  !

  open(deviceID, file=nmlfile_name, form='FORMATTED')

  read(deviceID, nml=Grid_Params)
  
  read(deviceID, nml=System_Params)
  
  read(deviceID, nml=TimeInteg_Params)
  
  read(deviceID, nml=DataOutput_Params)
  
  read(deviceID, nml=NumStability_Params)

  close(deviceID)

end subroutine read_simulation_parameters

subroutine readSimParams_And_SyncronizeCPPClass( &
  & cnmlfile_name, &
  & cgridParamList, csystemParamList, ctimeIntegParamList, &
  & cdataOutputParamList, cnumStabilityParamList &
  & ) bind(C, name='ReadSimParams_And_SyncronizeCPPClass')
  
  ! 宣言文 ; Declaration statements
  !
  character(len=1, kind=c_char), intent(in) :: cnmlfile_name(*)
  type(c_ptr), intent(out) :: cgridParamList
  type(c_ptr), intent(out) :: csystemParamList
  type(c_ptr), intent(out) :: ctimeIntegParamList
  type(c_ptr), intent(out) :: cdataOutputParamList
  type(c_ptr), intent(out) :: cnumStabilityParamList

  character(STRING) :: nmlfile_name
  type(GridParam_List), pointer :: ptr_gridParamList
  type(SystemParam_List), pointer :: ptr_systemParamList
  type(TimeIntegParam_List), pointer :: ptr_timeIntegParamList
  type(DataOutputParam_List), pointer :: ptr_dataOutputParamList
  type(NumStabilityParam_List), pointer :: ptr_numStabilityParamList
  
  call c_f_string(cnmlfile_name, nmlfile_name)
  
  call read_simulation_parameters(trim(nmlfile_name))
  
  ptr_gridParamList => GridParamList
  call f_c_string(GridParamList%gridFile_Path, GridParamList%gridFile_Path)

  ptr_systemParamList => SystemParamList

  ptr_timeIntegParamList => TimeIntegParamList

  ptr_dataOutputParamList => DataOutputParamList
  call f_c_string(DataOutputParamList%fieldzDataFilePath, DataOutputParamList%fieldzDataFilePath)
  call f_c_string(DataOutputParamList%fieldrDataFilePath, DataOutputParamList%fieldrDataFilePath)

  ptr_numStabilityParamList => NumStabilityParamList

  cgridParamList = c_loc(ptr_GridParamList)
  csystemParamList = c_loc(ptr_systemParamList)
  ctimeIntegParamList = c_loc(ptr_timeIntegParamList)
  cdataOutputParamList = c_loc(ptr_dataOutputParamList)
  cnumStabilityParamList = c_loc(ptr_NumStabilityParamList)

end subroutine readSimParams_And_SyncronizeCPPClass

end module SimParamList
