!= リスタートデータ, 初期値データ入出力
!
!= Restart data, initial data input/output
!
! Authors::   Yasuhiro MORIKAWA
! Version::   $Id: restart_file_io.F90,v 1.4 2008-11-08 04:44:48 morikawa Exp $ 
! Tag Name::  $Name: dcpam5-20081118 $
! Copyright:: Copyright (C) GFD Dennou Club, 2008. All rights reserved.
! License::   See COPYRIGHT[link:../../../COPYRIGHT]
!

module restart_file_io
  !
  != リスタートデータ, 初期値データ入出力
  !
  != Restart data, initial data input/output
  !
  ! <b>Note that Japanese and English are described in parallel.</b>
  !
  ! リスタートデータもしくは初期値データの入出力を行います. 
  ! 入力ファイル, 出力ファイル, データの出力の間隔は
  ! NAMELIST#restart_file_io_nml で設定します. 
  !
  ! リスタートデータの入力ファイルが指定されない場合, 
  ! initial_data モジュールで生成された初期値データを取得します. 
  !
  ! Restart data or initial data is input/output. 
  ! Settings of input file, output file, and interval of data output 
  ! is configured by "NAMELIST#restart_file_io_nml". 
  !
  ! If input file of restart data is not set, 
  ! initial data is generated in "initial_data" module, and 
  ! obtained data from the module. 
  !
  !== Procedures List
  !
  ! RestartFileOpen   :: リスタートファイルのオープン
  ! RestartFileOutput :: リスタートファイルへのデータ出力
  ! RestartFileClose  :: リスタートファイルのクローズ
  ! RestartFileGet    :: リスタートファイルの入力
  ! ------------      :: ------------
  ! RestartFileOpen   :: Open restart file
  ! RestartFileOutput :: Data output to restart file
  ! RestartFileClose  :: Close restart file
  ! RestartFileGet    :: Input restart file
  !
  !== NAMELIST
  !
  ! NAMELIST#restart_file_io_nml
  !

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

  ! 格子点設定
  ! Grid points settings
  !
  use gridset, only: imax, & ! 経度格子点数. 
                             ! Number of grid points in longitude
    &                jmax, & ! 緯度格子点数. 
                             ! Number of grid points in latitude
    &                kmax    ! 鉛直層数. 
                             ! Number of vertical level

  ! 日付および時刻の取り扱い
  ! Date and time handler
  !
  use dc_date_types, only: DC_DIFFTIME
                              ! 日時の差を表現するデータ型. 
                              ! Data type for difference about date and time

  ! 種別型パラメタ
  ! Kind type parameter
  !
  use dc_types, only: DP, &      ! 倍精度実数型. Double precision. 
    &                 STRING, &  ! 文字列.       Strings. 
    &                 TOKEN      ! キーワード.   Keywords. 

  ! メッセージ出力
  ! Message output
  !
  use dc_message, only: MessageNotify

  ! gtool4 データ出力
  ! Gtool4 data output
  !
  use gtool_history, only: GT_HISTORY

  ! 宣言文 ; Declaration statements
  !
  implicit none
  private
#ifdef LIB_MPI
  ! MPI ライブラリ
  ! MPI library
  !
  include 'mpif.h'
#endif

  ! 公開手続き
  ! Public procedure
  !
  public:: RestartFileOpen, RestartFileClose, RestartFileOutPut
  public:: RestartFileGet

  ! 公開変数
  ! Public variables
  !
  logical, save, public:: restart_file_io_inited = .false.
                              ! 初期設定フラグ. 
                              ! Initialization flag

  logical, save, public:: restart_file_opened = .false.
                              ! リスタートファイルのオープンに関するフラグ. 
                              ! Flag of restart file open

  character(STRING), save, public:: InputFile
                              ! 入力するリスタートデータのファイル名
                              ! Filename of input restart data

  character(STRING), save, public:: OutputFile
                              ! 出力するリスタートデータのファイル名
                              ! Filename of output restart data
  real, save, public:: IntValue
                              ! リスタートデータの出力間隔. 
                              ! Interval of restart data output
  character(TOKEN), save, public:: IntUnit
                              ! リスタートデータの出力間隔の単位. 
                              ! Unit for interval of restart data output

  ! 非公開変数
  ! Private variables
  !
  logical, save:: flag_init_data_save
                              ! 初期値データを作成する場合は, 
                              ! この引数に .true. を与えます. 
                              ! 
                              ! If initial data is created, 
                              ! give ".true." to this argument. 

  type(GT_HISTORY), save:: gthst_rst
                              ! リスタートデータ用 gtool_history#GT_HISTORY 変数
                              ! "gtool_history#GT_HISTORY" variable for restart data

  type(DC_DIFFTIME), save:: PrevOutputTime
                              ! 前回の出力時間. 
                              ! Previous output time

  type(DC_DIFFTIME), save:: IntTime
                              ! リスタートデータの出力時間. 
                              ! Time interval of restart data output

  character(*), parameter:: time_name = 'time'
                              ! 時刻の次元の変数名
                              ! Variable name of time dimension
  character(*), parameter:: deltime_name = 'deltime'
                              ! Δt の変数名
                              ! Variable name of Delta t


  character(*), parameter:: module_name = 'restart_file_io'
                              ! モジュールの名称. 
                              ! Module name
  character(*), parameter:: version = &
    & '$Name: dcpam5-20081118 $' // &
    & '$Id: restart_file_io.F90,v 1.4 2008-11-08 04:44:48 morikawa Exp $'
                              ! モジュールのバージョン
                              ! Module version

  ! INTERFACE 文 ; INTERFACE statements
  !
  interface RestartFileOpen
    module procedure RestartFileOpen
  end interface

  interface RestartFileClose
    module procedure RestartFileClose
  end interface

  interface RestartFileOutput
    module procedure RestartFileOutput
  end interface

  interface RestartFileGet
    module procedure RestartFileGet
  end interface

contains

  subroutine RestartFileOpen( flag_init_data )
    !
    ! リスタートファイルをオープンします. 
    !
    ! A restart file is opened. 
    !

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

    ! 出力ファイルの基本情報
    ! Basic information for output files
    ! 
    use fileset, only: &
      & FileTitle, &
                              ! 出力データファイルの表題.
                              ! Title of output data files
      & FileSource, &
                              ! データファイル作成の手段. 
                              ! Source of data file
      & FileInstitution
                              ! データファイルを最終的に変更した組織/個人. 
                              ! Institution or person that changes data files for the last time

    ! 物理定数設定
    ! Physical constants settings
    !
    use constants, only: PI   ! $ \pi $ .
                              ! 円周率.  Circular constant

    ! 座標データ設定
    ! Axes data settings
    !
    use axesset, only: &
      & x_Lon, &
                              ! $ \lambda $ [rad.] . 経度. Longitude
      & x_Lon_Weight, &
                              ! $ \Delta \lambda $ [rad.] . 
                              ! 経度座標重み. 
                              ! Weight of longitude
      & y_Lat, &
                              ! $ \varphi $ [rad.] . 緯度. Latitude
      & y_Lat_Weight, &
                              ! $ \Delta \varphi $ [rad.] . 
                              ! 緯度座標重み. 
                              ! Weight of latitude
      & z_Sigma, &
                              ! $ \sigma $ レベル (整数). 
                              ! Full $ \sigma $ level
      & r_Sigma, &
                              ! $ \sigma $ レベル (半整数). 
                              ! Half $ \sigma $ level
      & z_DelSigma
                              ! $ \Delta \sigma $ (整数). 
                              ! $ \Delta \sigma $ (Full)

    ! 時刻管理
    ! Time control
    !
    use timeset, only: &
      & DelTime, &            ! $ \Delta t $ [s]
      & StartTime, &          ! 計算開始時刻. 
                              ! Start time of calculation
      & StartDate, &          ! 計算開始日時. 
                              ! Start date of calculation
      & StartDateValid        ! 計算開始日時の有効性. 
                              ! Validation of start date of calculation

    ! gtool4 データ出力
    ! Gtool4 data output
    !
    use gtool_history, only: HistoryCreate, HistoryAddVariable, &
      & HistoryPut, HistoryAddAttr

    ! 文字列操作
    ! Character handling
    !
    use dc_string, only: StoA, CPrintf, LChar

    ! 日付および時刻の取り扱い
    ! Date and time handler
    !
    use dc_date, only: toChar, EvalByUnit, operator(+)

    ! 組み込み関数 PRESENT の拡張版関数
    ! Extended functions of intrinsic function "PRESENT"
    !
    use dc_present, only: present_and_true

    ! 宣言文 ; Declaration statements
    !
    implicit none
    logical, intent(in), optional:: flag_init_data
                              ! 初期値データを作成する場合は, 
                              ! この引数に .true. を与えます. 
                              ! 
                              ! If initial data is created, 
                              ! give ".true." to this argument. 

    ! 作業変数
    ! Work variables
    !
    character(STRING):: title_msg
                              ! 表題に付加するメッセージ. 
                              ! Message added to title
    real:: origin_time
                              ! 計算開始時刻. 
                              ! Start time of calculation
    character(STRING):: time_unit
                              ! 日時の単位. Units of date and time

    logical:: flag_mpi_init
#ifdef LIB_MPI
    integer:: err_mpi
#endif

    ! 実行文 ; Executable statement
    !

    ! 初期化
    ! Initialization
    !
    flag_init_data_save = present_and_true( flag_init_data )
    if ( .not. restart_file_io_inited ) call RestartFileInit
    if ( restart_file_opened ) return

    ! 表題に付加するメッセージの設定
    ! Configure message added to title
    !
    if ( .not. flag_init_data_save ) then
      title_msg = ' restart data'
    else
      title_msg = ' initial data'
    end if

    ! 時刻情報の取得
    ! Get time information
    !
    if ( .not. flag_init_data_save ) then
      origin_time = EvalByUnit( StartTime + IntTime, IntUnit )
    else
      origin_time = EvalByUnit( StartTime, IntUnit )
    end if

    if ( StartDateValid ) then
      time_unit = trim(IntUnit) // ' since ' // toChar(StartDate)
    else
      time_unit = IntUnit
    end if

#ifdef LIB_MPI
    ! MPI における初期化が行われているかを確認する. 
    ! Confirm initialization of MPI
    !
    call MPI_Initialized(flag_mpi_init, err_mpi)
#else
    flag_mpi_init = .false.
#endif

    ! リスタートファイルのオープン
    ! Open a restart file
    !
    call HistoryCreate( &
      &      file = OutputFile,   &
      &     title = trim(FileTitle) // trim(title_msg), &          ! (in)
      &    source = FileSource, institution = FileInstitution, &   ! (in)
      &      dims = StoA( 'lon', 'lat', 'sig', 'sigm', time_name ), & ! (in)
      &  dimsizes = (/ imax, jmax, kmax, kmax + 1, 0 /), &         ! (in)
      & longnames = StoA( 'longitude', 'latitude', &
      &                   'sigma at layer midpoints', &
      &                   'sigma at layer end-points (half level)', &
      &                   time_name ), &                           ! (in)
      &     units = StoA( 'degree_east', 'degree_north', &
      &                   '1', '1', time_unit ), &                 ! (in)
      &         origin = origin_time, &       ! (in) optional
      &       interval = IntValue, &          ! (in) optional
      & flag_mpi_split = flag_mpi_init, &     ! (in) optional
      &        history = gthst_rst )          ! (out) optional

    ! $ \Delta t $ に関する情報を追加. 
    !   (これがリスタートデータを示すフラグとなる)
    ! Add information about $ \Delta t $. 
    !   (This is used as a flag that shows that this data is restart data)
    !
    if ( .not. present_and_true( flag_init_data ) ) then
      call HistoryAddVariable( &
        & varname = deltime_name, &         ! (in)
        & dims = StoA(''), &                ! (in)
        & longname = 'delta time', &        ! (in)
        & units = 'sec', xtype = 'float', & ! (in)
        & history = gthst_rst )             ! (inout)
      call HistoryPut( &
        & varname = deltime_name, &         ! (in)
        & array = (/ DelTime /), &          ! (in)
        & history = gthst_rst )             ! (inout)
      call HistoryAddAttr( &
        & varname = deltime_name, attrname = 'comment', &        ! (in)
        & value = 'this is used as a flag that shows ' // &
        &         'that this data is restart data in dcpam. ', & ! (in)
        & history = gthst_rst )                                  ! (inout)
    end if

    ! 座標データの設定
    ! Axes data settings
    !
    call HistoryAddAttr( &
      & varname = 'lon', attrname = 'standard_name', &   ! (in)
      & value = 'longitude', &                           ! (in)
      & history = gthst_rst )                            ! (inout)
    call HistoryAddAttr( &
      & varname = 'lat', attrname = 'standard_name', &   ! (in)
      & value = 'latitude', &                            ! (in)
      & history = gthst_rst )                            ! (inout)
    call HistoryAddAttr( &
      & varname = 'sig', attrname = 'standard_name', &   ! (in)
      & value = 'atmosphere_sigma_coordinate', &         ! (in)
      & history = gthst_rst )                            ! (inout)
    call HistoryAddAttr( &
      & varname = 'sigm', attrname = 'standard_name', &  ! (in)
      & value = 'atmosphere_sigma_coordinate', &         ! (in)
      & history = gthst_rst )                            ! (inout)
    call HistoryAddAttr( &
      & varname = time_name, attrname = 'standard_name', &  ! (in)
      & value = 'time', &                                ! (in)
      & history = gthst_rst )                            ! (inout)
    call HistoryAddAttr( &
      & varname = 'sig', attrname = 'positive', &        ! (in)
      & value = 'down', &                                ! (in)
      & history = gthst_rst )                            ! (inout)
    call HistoryAddAttr( &
      & varname = 'sigm', attrname = 'positive', &       ! (in)
      & value = 'down', &                                ! (in)
      & history = gthst_rst )                            ! (inout)

    call HistoryPut( &
      & varname = 'lon', &               ! (in)
      & array = x_Lon / PI * 180.0_DP, & ! (in)
      & history = gthst_rst )            ! (inout)
    call HistoryPut( &
      & varname = 'lat', &               ! (in)
      & array = y_Lat / PI * 180.0_DP, & ! (in)
      & history = gthst_rst )            ! (inout)
    call HistoryPut( &
      & varname = 'sig', &               ! (in)
      & array = z_Sigma, &               ! (in)
      & history = gthst_rst )            ! (inout)
    call HistoryPut( & 
      & varname = 'sigm', &              ! (in)
      & array = r_Sigma, &               ! (in)
      & history = gthst_rst )            ! (inout)

    ! 座標重みの設定
    ! Axes weights settings
    !
    call HistoryAddVariable( &
      & varname = 'lon_weight', &                           ! (in)
      & dims = StoA('lon'), &                               ! (in)
      & longname = 'weight for integration in longitude', & ! (in)
      & units = 'radian', xtype = 'double', &               ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryAddAttr( &
      & varname = 'lon', attrname = 'gt_calc_weight', &     ! (in)
      & value = 'lon_weight', &                             ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryPut( &
      & varname = 'lon_weight', array = x_Lon_Weight, &     ! (in)
      & history = gthst_rst )                               ! (inout)

    call HistoryAddVariable( &
      & varname = 'lat_weight', &                           ! (in)
      & dims = StoA('lat'), &                               ! (in)
      & longname = 'weight for integration in latitude', &  ! (in)
      & units = 'radian', xtype = 'double', &               ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryAddAttr( &
      & varname = 'lat', attrname = 'gt_calc_weight', &     ! (in)
      & value = 'lat_weight', &                             ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryPut( &
      & varname = 'lat_weight', array = y_Lat_Weight, &     ! (in)
      & history = gthst_rst )                               ! (inout)

    call HistoryAddVariable( &
      & varname = 'sig_weight', &                           ! (in)
      & dims = StoA('sig'), &                               ! (in)
      & longname = 'weight for integration in sigma', &     ! (in)
      & units = '1', xtype = 'double', &                    ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryAddAttr( &
      & varname = 'sig', attrname = 'gt_calc_weight', &     ! (in)
      & value = 'sig_weight', &                             ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryPut( &
      & varname = 'sig_weight', array = z_DelSigma, &       ! (in)
      & history = gthst_rst )                               ! (inout)

    ! 予報変数の設定
    ! Predictional variables settings
    !
    call HistoryAddVariable( &
      & varname = 'UB', &                                   ! (in)
      & dims = StoA('lon', 'lat', 'sig', time_name), &      ! (in)
      & longname = 'eastward wind (at t-\Delta t)', &       ! (in)
      & units = 'm s-1', xtype = 'double', &                ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryAddVariable( &
      & varname = 'VB', &                                   ! (in)
      & dims = StoA('lon', 'lat', 'sig', time_name), &      ! (in)
      & longname = 'northward wind (at t-\Delta t)', &      ! (in)
      & units = 'm s-1', xtype = 'double', &                ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryAddVariable( &
      & varname = 'TempB', &                                ! (in)
      & dims = StoA('lon', 'lat', 'sig', time_name), &      ! (in)
      & longname = 'temperature (at t-\Delta t)', &         ! (in)
      & units = 'K', xtype = 'double', &                    ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryAddVariable( &
      & varname = 'QVapB', &                                ! (in)
      & dims = StoA('lon', 'lat', 'sig', time_name), &      ! (in)
      & longname = 'specific humidity (at t-\Delta t)', &   ! (in)
      & units = 'kg kg-1', xtype = 'double', &              ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryAddVariable( &
      & varname = 'PsB', &                                  ! (in)
      & dims = StoA('lon', 'lat', time_name), &             ! (in)
      & longname = 'surface pressure (at t-\Delta t)', &    ! (in)
      & units = 'Pa', xtype = 'double', &                   ! (in)
      & history = gthst_rst )                               ! (inout)

    call HistoryAddVariable( &
      & varname = 'UN', &                                   ! (in)
      & dims = StoA('lon', 'lat', 'sig', time_name), &      ! (in)
      & longname = 'eastward wind (at t)', &                ! (in)
      & units = 'm s-1', xtype = 'double', &                ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryAddVariable( &
      & varname = 'VN', &                                   ! (in)
      & dims = StoA('lon', 'lat', 'sig', time_name), &      ! (in)
      & longname = 'northward wind (at t)', &               ! (in)
      & units = 'm s-1', xtype = 'double', &                ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryAddVariable( &
      & varname = 'TempN', &                                ! (in)
      & dims = StoA('lon', 'lat', 'sig', time_name), &      ! (in)
      & longname = 'temperature (at t)', &                  ! (in)
      & units = 'K', xtype = 'double', &                    ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryAddVariable( &
      & varname = 'QVapN', &                                ! (in)
      & dims = StoA('lon', 'lat', 'sig', time_name), &      ! (in)
      & longname = 'specific humidity (at t)', &            ! (in)
      & units = 'kg kg-1', xtype = 'double', &              ! (in)
      & history = gthst_rst )                               ! (inout)
    call HistoryAddVariable( &
      & varname = 'PsN', &                                  ! (in)
      & dims = StoA('lon', 'lat', time_name), &             ! (in)
      & longname = 'surface pressure (at t)', &             ! (in)
      & units = 'Pa', xtype = 'double', &                   ! (in)
      & history = gthst_rst )                               ! (inout)

    restart_file_opened = .true.
  end subroutine RestartFileOpen

  !-------------------------------------------------------------------

  subroutine RestartFileOutput( &
    & xyz_UB, xyz_VB, xyz_TempB, xyz_QVapB, xy_PsB, &   ! (in)
    & xyz_UN, xyz_VN, xyz_TempN, xyz_QVapN, xy_PsN  &   ! (in)
    & )
    !
    ! リスタートデータの出力を行います. 
    !
    ! Output restart data

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

    ! gtool4 データ出力
    ! Gtool4 data output
    !
    use gtool_history, only: HistoryPut

    ! 時刻管理
    ! Time control
    !
    use timeset, only: TimeN  ! ステップ $ t $ の時刻. 
                              ! Time of step $ t $. 

    ! 日付および時刻の取り扱い
    ! Date and time handler
    !
    use dc_date, only: operator(<), operator(-), DCDiffTimePutLine

    ! 宣言文 ; Declaration statements
    !
    implicit none
    real(DP), intent(in):: xyz_UB  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ u (t-\Delta t) $ .   東西風速. Eastward wind
    real(DP), intent(in):: xyz_VB  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ v (t-\Delta t) $ .   南北風速. Northward wind
    real(DP), intent(in):: xyz_TempB  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ T (t-\Delta t) $ .   温度. Temperature
    real(DP), intent(in):: xyz_QVapB  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ q (t-\Delta t) $ .   比湿. Specific humidity
    real(DP), intent(in):: xy_PsB (0:imax-1, 1:jmax)
                              ! $ p_s (t-\Delta t) $ . 地表面気圧. Surface pressure
    real(DP), intent(in):: xyz_UN  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ u (t) $ .     東西風速. Eastward wind
    real(DP), intent(in):: xyz_VN  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ v (t) $ .     南北風速. Northward wind
    real(DP), intent(in):: xyz_TempN  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ T (t) $ .     温度. Temperature
    real(DP), intent(in):: xyz_QVapN  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ q (t) $ .     比湿. Specific humidity
    real(DP), intent(in):: xy_PsN (0:imax-1, 1:jmax)
                              ! $ p_s (t) $ .   地表面気圧. Surface pressure

    ! 作業変数
    ! Work variables
    !

    ! 実行文 ; Executable statement
    !

    if ( .not. restart_file_opened ) call RestartFileOpen

    ! 出力タイミングのチェック
    ! Check output timing
    !
    if ( .not. flag_init_data_save .and. &
      &  TimeN - PrevOutputTime < IntTime ) return
    PrevOutputTime = TimeN

    ! データ出力
    ! Data output
    !
    call HistoryPut( &
      & 'UB', xyz_UB, history = gthst_rst ) ! (in)
    call HistoryPut( &
      & 'VB', xyz_VB, history = gthst_rst ) ! (in)
    call HistoryPut( &
      & 'TempB', xyz_TempB, history = gthst_rst ) ! (in)
    call HistoryPut( &
      & 'QVapB', xyz_QVapB, history = gthst_rst ) ! (in)
    call HistoryPut( &
      & 'PsB', xy_PsB, history = gthst_rst ) ! (in)

    call HistoryPut( &
      & 'UN', xyz_UN, history = gthst_rst ) ! (in)
    call HistoryPut( &
      & 'VN', xyz_VN, history = gthst_rst ) ! (in)
    call HistoryPut( &
      & 'TempN', xyz_TempN, history = gthst_rst ) ! (in)
    call HistoryPut( &
      & 'QVapN', xyz_QVapN, history = gthst_rst ) ! (in)
    call HistoryPut( &
      & 'PsN', xy_PsN, history = gthst_rst ) ! (in)

  end subroutine RestartFileOutput

  !-------------------------------------------------------------------

  subroutine RestartFileClose
    !
    ! リスタートデータファイル出力の終了処理を行います. 
    !
    ! Terminate restart data files output. 

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

    ! gtool4 データ出力
    ! Gtool4 data output
    !
    use gtool_history, only: HistoryClose

    ! 宣言文 ; Declaration statements
    !
    implicit none

    ! 作業変数
    ! Work variables
    !

    ! 実行文 ; Executable statement
    !
    if ( .not. restart_file_opened ) return

    call HistoryClose( history = gthst_rst ) ! (inout)

    restart_file_opened = .false.
  end subroutine RestartFileClose

  !-------------------------------------------------------------------

  subroutine RestartFileGet( &
    & xyz_UB, xyz_VB, xyz_TempB, xyz_QVapB, xy_PsB, & ! (out)
    & xyz_UN, xyz_VN, xyz_TempN, xyz_QVapN, xy_PsN, & ! (out)
    & flag_initial &                                  ! (out) optional
    & )
    !
    ! リスタートデータの入力を行います. 
    ! リスタートデータが存在しない場合には, 
    ! initial_data モジュールを用いて, 初期値生成を行います. 
    !
    ! Input restart data. 
    ! If restart data is not exist, 
    ! initial data is created by "initial_data". 


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

    ! 初期値データ (リスタートデータ) 提供
    ! Prepare initial data (restart data)
    !
    use initial_data, only: InitDataGet

    ! 時刻管理
    ! Time control
    !
    use timeset, only: &
      & StartTime             ! 計算開始時刻. 

    ! gtool4 データ入力
    ! Gtool4 data input
    !
    use gtool_history, only: HistoryGet

    ! 日付および時刻の取り扱い
    ! Date and time handler
    !
    use dc_date, only: EvalByUnit

    ! 文字列操作
    ! Character handling
    !
    use dc_string, only: toChar

    ! 宣言文 ; Declaration statements
    !
    implicit none
    real(DP), intent(out):: xyz_UB  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ u (t-\Delta t) $ .   東西風速. Eastward wind
    real(DP), intent(out):: xyz_VB  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ v (t-\Delta t) $ .   南北風速. Northward wind
    real(DP), intent(out):: xyz_TempB  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ T (t-\Delta t) $ .   温度. Temperature
    real(DP), intent(out):: xyz_QVapB  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ q (t-\Delta t) $ .   比湿. Specific humidity
    real(DP), intent(out):: xy_PsB (0:imax-1, 1:jmax)
                              ! $ p_s (t-\Delta t) $ . 地表面気圧. Surface pressure
    real(DP), intent(out):: xyz_UN  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ u (t) $ .     東西風速. Eastward wind
    real(DP), intent(out):: xyz_VN  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ v (t) $ .     南北風速. Northward wind
    real(DP), intent(out):: xyz_TempN  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ T (t) $ .     温度. Temperature
    real(DP), intent(out):: xyz_QVapN  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ q (t) $ .     比湿. Specific humidity
    real(DP), intent(out):: xy_PsN (0:imax-1, 1:jmax)
                              ! $ p_s (t) $ .   地表面気圧. Surface pressure
    logical, intent(out), optional:: flag_initial
                              ! リスタートデータを読み込む場合には, 
                              ! .false. が, 初期値データを読み込む場合には
                              ! .true. が返ります. 
                              ! 
                              ! If restart data is loaded, .false. is returned.
                              ! On the other hand, if initial data is loaded, 
                              ! .true. is returned. 

    ! 作業変数
    ! Work variables
    !
    character(TOKEN):: time_range
                              ! 時刻の指定. 
                              ! Specification of time
    real:: deltime_value
                              ! 'deltime' 変数の値. 
                              ! Value of 'deltime' variable. 
    logical:: deltime_get_err
                              ! 'deltime' 変数取得時のエラーフラグ. 
                              ! Error flag when 'deltime' variable is gotten. 

    logical:: flag_mpi_init
#ifdef LIB_MPI
    integer:: err_mpi
#endif

    ! 実行文 ; Executable statement
    !

    if ( .not. restart_file_io_inited ) call RestartFileInit

    ! データを initial_data モジュールから取得
    ! Data is input from "initial_data" module
    ! 
    if ( trim(InputFile) == '' ) then
      call InitDataGet( &
        & xyz_UB, xyz_VB, xyz_TempB, xyz_QVapB, xy_PsB, &  ! (out)
        & xyz_UN, xyz_VN, xyz_TempN, xyz_QVapN, xy_PsN )   ! (out)

      if ( present(flag_initial) ) flag_initial = .true.

    ! データを InputFile から取得
    ! Data is input from InputFile
    ! 
    else

      ! 初期値データかリスタートデータかのチェック
      ! Check whether input data is initial data or restart data
      ! 
      call HistoryGet( &
        & InputFile, deltime_name, &  ! (in)
        & array = deltime_value, &    ! (out)
        & err = deltime_get_err )     ! (out)

      if ( present(flag_initial) ) then
        if ( deltime_get_err ) then
          flag_initial = .true.
        else
          if ( deltime_value > 0.0 ) then
            flag_initial = .false.
          else
            flag_initial = .true.
          end if
        end if
      end if

      ! 時刻情報の取得
      ! Get time information
      !
      time_range = time_name // '=' // &
        &          toChar( EvalbyUnit( StartTime, IntUnit ) )

#ifdef LIB_MPI
      ! MPI における初期化が行われているかを確認する. 
      ! Confirm initialization of MPI
      !
      call MPI_Initialized(flag_mpi_init, err_mpi)
#else
      flag_mpi_init = .false.
#endif

      ! データ入力
      ! Data input
      ! 
      call HistoryGet( &
        & InputFile, 'UB', range = time_range, &  ! (in)
        & array = xyz_UB, &                       ! (out)
        & flag_mpi_split = flag_mpi_init )        ! (in) optional
      call HistoryGet( &
        & InputFile, 'VB', range = time_range, &  ! (in)
        & array = xyz_VB, &                       ! (out)
        & flag_mpi_split = flag_mpi_init )        ! (in) optional
      call HistoryGet( &
        & InputFile, 'TempB', range = time_range, &  ! (in)
        & array = xyz_TempB, &                       ! (out)
        & flag_mpi_split = flag_mpi_init )           ! (in) optional
      call HistoryGet( &
        & InputFile, 'QVapB', range = time_range, &  ! (in)
        & array = xyz_QVapB, &                       ! (out)
        & flag_mpi_split = flag_mpi_init )           ! (in) optional
      call HistoryGet( &
        & InputFile, 'PsB', range = time_range, &  ! (in)
        & array = xy_PsB, &                        ! (out)
        & flag_mpi_split = flag_mpi_init )         ! (in) optional

      call HistoryGet( &
        & InputFile, 'UN', range = time_range, &  ! (in)
        & array = xyz_UN, &                       ! (out)
        & flag_mpi_split = flag_mpi_init )        ! (in) optional
      call HistoryGet( &
        & InputFile, 'VN', range = time_range, &  ! (in)
        & array = xyz_VN, &                       ! (out)
        & flag_mpi_split = flag_mpi_init )        ! (in) optional
      call HistoryGet( &
        & InputFile, 'TempN', range = time_range, &  ! (in)
        & array = xyz_TempN, &                       ! (out)
        & flag_mpi_split = flag_mpi_init )           ! (in) optional
      call HistoryGet( &
        & InputFile, 'QVapN', range = time_range, &  ! (in)
        & array = xyz_QVapN, &                       ! (out)
        & flag_mpi_split = flag_mpi_init )           ! (in) optional
      call HistoryGet( &
        & InputFile, 'PsN', range = time_range, &  ! (in)
        & array = xy_PsN, &                        ! (out)
        & flag_mpi_split = flag_mpi_init )         ! (in) optional

    end if

  end subroutine RestartFileGet

  !-------------------------------------------------------------------

  subroutine RestartFileInit
    !
    ! restart_file_io モジュールの初期化を行います. 
    ! NAMELIST#restart_file_io_nml の読み込みはこの手続きで行われます. 
    !
    ! "restart_file_io" module is initialized. 
    ! "NAMELIST#restart_file_io_nml" is loaded in this procedure. 
    !

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

    ! 時刻管理
    ! Time control
    !
    use timeset, only: &
      & StartTime             ! 計算開始時刻. 
                              ! Start time of calculation

    ! NAMELIST ファイル入力に関するユーティリティ
    ! Utilities for NAMELIST file input
    !
    use namelist_util, only: namelist_filename, NmlutilMsg

    ! 日付および時刻の取り扱い
    ! Date and time handler
    !
    use dc_date, only: DCDiffTimeCreate, operator(-)

    ! ファイル入出力補助
    ! File I/O support
    !
    use dc_iounit, only: FileOpen

    ! 種別型パラメタ
    ! Kind type parameter
    !
    use dc_types, only: STDOUT ! 標準出力の装置番号. Unit number of standard output

    ! 宣言文 ; Declaration statements
    !
    implicit none

    ! 作業変数
    ! Work variables
    !
    integer:: unit_nml        ! NAMELIST ファイルオープン用装置番号. 
                              ! Unit number for NAMELIST file open
    integer:: iostat_nml      ! NAMELIST 読み込み時の IOSTAT. 
                              ! IOSTAT of NAMELIST read

    ! NAMELIST 変数群
    ! NAMELIST group name
    !
    namelist /restart_file_io_nml/ &
      & InputFile, &
      & OutputFile, &
      & IntValue, IntUnit
          !
          ! デフォルト値については初期化手続 "restart_file_io#RestartFileInit" 
          ! のソースコードを参照のこと. 
          !
          ! Refer to source codes in the initialization procedure
          ! "restart_file_io#RestartFileInit" for the default values. 
          !


    ! 実行文 ; Executable statement
    !

    if ( restart_file_io_inited ) return
    call InitCheck

    ! デフォルト値の設定
    ! Default values settings
    !
    InputFile  = ''
    if ( .not. flag_init_data_save ) then
      OutputFile = 'restart.nc'
    else
      OutputFile = 'init.nc'
    end if
    IntValue   = 1.0
    IntUnit    = 'day'

    ! NAMELIST の読み込み
    ! NAMELIST is input
    !
    if ( trim(namelist_filename) /= '' ) then
      call FileOpen( unit_nml, &          ! (out)
        & namelist_filename, mode = 'r' ) ! (in)

      rewind( unit_nml )
      read( unit_nml, &         ! (in)
        & nml = restart_file_io_nml, &  ! (out)
        & iostat = iostat_nml ) ! (out)
      close( unit_nml )

      call NmlutilMsg( iostat_nml, module_name ) ! (in)
      if ( iostat_nml == 0 ) write( STDOUT, nml = restart_file_io_nml )
    end if

    ! 出力時間間隔の設定
    ! Configure time interval of output
    !
    call DCDiffTimeCreate( IntTime, & ! (out)
      & IntValue, IntUnit )           ! (in)
    PrevOutputTime = StartTime

    ! 印字 ; Print
    !
    call MessageNotify( 'M', module_name, '----- Initialization Messages -----' )
    call MessageNotify( 'M', module_name, 'Input:: ' )
    call MessageNotify( 'M', module_name, '  InputFile  = %c', c1 = trim(InputFile) )
    call MessageNotify( 'M', module_name, 'Output:: ' )
    call MessageNotify( 'M', module_name, '  OutputFile = %c', c1 = trim(OutputFile) )
    call MessageNotify( 'M', module_name, '  IntTime    = %r [%c]', r = (/ IntValue /), c1 = trim(IntUnit) )
    call MessageNotify( 'M', module_name, '-- version = %c', c1 = trim(version) )

    restart_file_io_inited = .true.
  end subroutine RestartFileInit

  !-------------------------------------------------------------------

  subroutine InitCheck
    !
    ! 依存モジュールの初期化チェック
    !
    ! Check initialization of dependency modules

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

    ! NAMELIST ファイル入力に関するユーティリティ
    ! Utilities for NAMELIST file input
    !
    use namelist_util, only: namelist_util_inited

    ! 出力ファイルの基本情報管理
    ! Management basic information for output files
    !
    use fileset, only: fileset_inited

    ! 格子点設定
    ! Grid points settings
    !
    use gridset, only: gridset_inited

    ! 物理定数設定
    ! Physical constants settings
    !
    use constants, only: constants_inited

    ! 座標データ設定
    ! Axes data settings
    !
    use axesset, only: axesset_inited

    ! 時刻管理
    ! Time control
    !
    use timeset, only: timeset_inited


    ! 実行文 ; Executable statement
    !

    if ( .not. namelist_util_inited ) &
      & call MessageNotify( 'E', module_name, '"namelist_util" module is not initialized.' )

    if ( .not. fileset_inited ) &
      & call MessageNotify( 'E', module_name, '"fileset" module is not initialized.' )

    if ( .not. gridset_inited ) &
      & call MessageNotify( 'E', module_name, '"gridset" module is not initialized.' )

    if ( .not. constants_inited ) &
      & call MessageNotify( 'E', module_name, '"constants" module is not initialized.' )

    if ( .not. axesset_inited ) &
      & call MessageNotify( 'E', module_name, '"axesset" module is not initialized.' )

    if ( .not. timeset_inited ) &
      & call MessageNotify( 'E', module_name, '"timeset" module is not initialized.' )


  end subroutine InitCheck

end module restart_file_io
