!
!>
!!
!!
!!
!! @attention ここで読み込まれる NetCDF ファイルは, IGMBaseLib の IcGrid_ncWriter_mod モジュールを用いて書き出されたことを,
!! 前提としている.
!!
module IcGrid_Field_Reader

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

  !* gtool5 ****
  !*

  ! 種類型パラメータ
  ! Kind type parameter
  !
  use dc_types, only: DP ! 倍精度実数型. Double precision.

  !* IGMBaseLib **
  !*

  ! 正二十面体格子データの管理
  ! Managerof Icosahedral grid data
  !
  use IcGrid2D_FVM_Manager, only: &
    & IcGrid2D_FVM

  ! 正二十面体格子上の物理場データの管理
  ! Manager of physical filed data
  !
  use Field_IcGrid2D_Manager, only: &
    & Field_IcGrid2D, get_field2D_name

  ! 正二十面体格子データを管理するクラス
  ! Manager of Icosahedral grid data
  !
  use IcGrid3D_FVM_Manager, only: &
    & IcGrid3D_FVM, &
    & IcGrid3D_FVM_Init

  ! 正二十面体格子上の物理場データの管理
  ! Manager of physical file data on icosahedral grid
  !
  use Field_IcGrid3D_Manager, only: &
    & Field_IcGrid3D, &
    & Field_IcGrid3D_Init, get_field3D_name

  ! NetCDF から正二十面格子の格子データ及び物理場データの読み込み
  ! NetCDF Reader for icosahedral grid data and physical fields data on the grid
  !
  use IcGrid_ncReader_mod, only: &
    & IcGrid_ncReader, IcGrid_ncReader_Init, &
    & open_ncFile, close_ncFile, &
    & read_GridData, read_FieldData, read_Simulation_Parameter

  ! 宣言文 ; Declaration statements
  !
  implicit none
  private

  ! 公開手続き
  ! Public statements
  !
  public :: IcGrid_Field_Reader_Init, IcGrid_Field_Reader_Final
  public :: read_NcHeaderIcGridData, read_Field_IcGrid2d_Data, read_Field_IcGrid3d_Data

  ! interface 文 ; interface statements
  !
  !
  interface IcGrid_Field_Reader_Init
    module procedure IcGrid2D_Field_Reader_Init
    module procedure IcGrid3D_Field_Reader_Init
  end interface IcGrid_Field_Reader_Init

  ! 非公開変数
  ! Private variables
  !

  !
  !
  type(IcGrid_ncReader), save :: ncReader


contains

!
!> IcGrid2D_Field_Reader モジュールを初期化する.
!!
!! 本モジュールの変数である ncReader を初期化する.
!! 実際に正二十面格子データが読み込まれるのは, read_NcHeaderIcGridData を呼ぶ時である.
!!
!! @param[in] ncFileName 読み込む NetCDF ファイルの名前.
!! @param[in,out] icgrid2D 読み込んだ正二十面格子データを格納する構造型 IcGrid2D_FVM の変数.
!!
subroutine IcGrid2D_Field_Reader_Init(ncFileName, icgrid2D)

  ! 宣言文 ; Declaration statements
  !
  character(*), intent(in) :: ncFileName
  type(IcGrid2D_FVM), intent(inout) :: icgrid2d

  ! 実行文 ; Executable statements
  !

  ! IcGrid_ncReader クラスのオブジェクトの初期化を行い, netCDF ファイルを開く.
  call IcGrid_ncReader_Init(ncReader, icgrid2D)
  call open_ncFile(ncReader, ncFileName)

end subroutine IcGrid2D_Field_Reader_Init

subroutine IcGrid3D_Field_Reader_Init(ncFileName, icgrid3D)

  ! 宣言文 ; Declaration statements
  !
  character(*), intent(in) :: ncFileName
  type(IcGrid3D_FVM), intent(inout) :: icgrid3d

  ! 実行文 ; Executable statements
  !

  ! IcGrid_ncReader クラスのオブジェクトの初期化を行い, netCDF ファイルを開く.
  call IcGrid_ncReader_Init(ncReader, icgrid3D)
  call open_ncFile(ncReader, ncFileName)

end subroutine IcGrid3D_Field_Reader_Init

!
!> IcGrid2D_Field_Reader モジュールを最終化する.
!!
!! 本モジュールの変数である ncReader を最終化する.
!!
subroutine IcGrid_Field_Reader_Final()

  ! 実行文 ; Executable statements
  !
  call close_ncFile(ncReader)

end subroutine IcGrid_Field_Reader_Final

!
!> NetCDF ファイルからシミュレーションパラメータと正二十面格子データを読み込む.
!!
!! 読み込まれたシミュレーションパラメータは, 出力時間間隔, 積分時間, タイムステップであり,
!! これらの情報は引数によって返される.
!! 一方に, 読み込まれた正二十面格子データは, IcGrid_Field_Reader_Init で与えた, 構造型 IcGrid2D_FVM の変数に格納される.
!!
!! @attention この手続きを呼ぶ前に, IcGrid2D_Field_Reader_Init によって本モジュールは初期化されなければならない.
!!
!! @param[in,out] outpu_tick 出力時間間隔 [sec].
!! @param[in,out] integration_time 積分時間 [sec].
!! @param[in,out] time_step タイムステップ [sec].
!!
subroutine read_NcHeaderIcGridData(output_tick, integration_time, time_step)

  ! 宣言文 ; Declaration statement
  !
  real(DP), intent(inout) :: output_tick
  real(DP), intent(inout) :: integration_time
  real(DP), intent(inout) :: time_step

  ! 作業変数
  ! Work variables
  !

  ! 実行文 ; Executable statement
  !

  ! netCDF ファイルからシミュレーションパラメータを読み込む.
  call read_Simulation_Parameter(ncReader, integration_time, time_step, output_tick)

  ! netCDF ファイルから座標データを読み込む.
  call read_GridData(ncReader)

end subroutine read_NcHeaderIcGridData

!
!> NetCDF ファイルから, 特定のタイムレベルの正二十面体格子上の物理量データを読み込み,
!! 構造型 Field_IcGrid2D の変数に格納する.
!!
!! @attention この手続きを呼ぶ前に, IcGrid2D_Field_Reader_Init によって本モジュールは初期化されなければならない.
!!
!! @param[in]     time_level 物理場データの読み込みを行うタイムレベル.
!! @param[in,out] fields     読み込む物理場データに対応する構造型 Field_IcGrid2D の変数の配列.
!! @param[in]     field_num
!!
subroutine read_Field_IcGrid2d_Data(time_level, fields)

  ! 宣言文 ; Declaration statement
  !
  integer, intent(in) :: time_level
  type(Field_IcGrid2D), intent(inout) :: fields(:)

  ! 作業変数
  ! Work variables
  !
  integer :: fieldID
  integer :: field_num

  ! 実行文 ; Executable statement
  !

  field_num = size(fields)

  ! IcGrid_ncReader モジュールを使って, netCDF ファイルに書き込まれた正二十面体格子上の各物理量データを読み込み,
  ! それらに対応する構造型 Field_IcGrid2D の変数の配列にそれぞれ格納する.

  do fieldID=1,field_num

    ! タイムレベル time_level の物理量データを, netCDF ファイルから読み込み,
    ! Field_IcGrid2D クラスのオブジェクトに格納する.
    call read_FieldData(ncReader, trim(get_field2D_name(fields(fieldID))), fields(fieldID), time_level)
  end do

end subroutine read_Field_IcGrid2d_Data

!
!> IGMBaseLib の IcGrid_ncWriter クラスを用いて書き出された netCDF ファイルから, あるタイムレベルの正二十面体格子上の物理量データを読み込み,
!! Field_IcGrid2D クラスのオブジェクトに格納する.
!!
!! @param[in]     ncFileName
!! @param[in]     icgrid
!! @param[in]     time_level
!! @param[in,out] fields
!!
subroutine read_Field_IcGrid3d_Data( &
  & time_level, &
  & fields      &
  & )

  ! 宣言文 ; Declaration statement
  !
  integer, intent(in) :: time_level
  type(Field_IcGrid3D), intent(inout) :: fields(:)

  ! 作業変数
  ! Work variables
  !
  integer :: fieldID
  integer :: field_num

  ! 実行文 ; Executable statement
  !

  field_num = size(fields)

  ! IcGrid_ncReader クラスを使って, netCDF ファイルに書き込まれた正二十面体格子上の各物理量データを読み込み,
  ! それらに対応する Field_IcGrid2D クラスのオブジェトの配列にそれぞれ格納する.

  do fieldID=1,field_num

    ! タイムレベル time_level の物理量データを, netCDF ファイルから読み込み,
    ! Field_IcGrid2D クラスのオブジェクトに格納する.
    !   write(*,*) get_field3D_name(fields(fieldID))

    call read_FieldData(ncReader, trim(get_field3D_name(fields(fieldID))), fields(fieldID), time_level)
  end do

end subroutine read_Field_IcGrid3d_Data

end module IcGrid_Field_Reader
