!= リスタートデータ, 初期値データ入出力
!
!= Restart data, initial data input/output
!
! Authors::   Yoshiyuki O. Takahashi, Yasuhiro MORIKAWA
! Version::   $Id: restart_file_io.f90,v 1.13 2010-03-24 12:19:15 yot Exp $
! Tag Name::  $Name:  $
! 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/initial file
  ! RestartFileOutput :: Data output to restart/initial file
  ! RestartFileClose  :: Close restart/initial file
  ! RestartFileGet    :: Input restart/initial 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

  ! 公開手続き
  ! 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 (numerical value)
  character(TOKEN), save, public:: IntUnit
                              ! リスタートデータの出力間隔 (単位). 
                              ! Interval of restart data output (unit)
  type(DC_DIFFTIME), save, public:: IntTime
                              ! リスタートデータの出力間隔. 
                              ! 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
  logical, save:: flag_output_end
                              ! 計算最終時刻の出力完了のフラグ. 
                              ! Flag for completion of output at the end time of calculation

  character(*), parameter:: module_name = 'restart_file_io'
                              ! モジュールの名称. 
                              ! Module name
  character(*), parameter:: version = &
    & '$Name:  $' // &
    & '$Id: restart_file_io.f90,v 1.13 2010-03-24 12:19:15 yot Exp $'
                              ! モジュールのバージョン
                              ! Module version

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

  interface RestartFileClose
    module procedure RestartFileClose
  end interface

  interface RestartFileOutput
    module procedure RestartFileOutput0
    module procedure InitialFileOutput
  end interface

  interface RestartFileGet
    module procedure RestartFileGet
  end interface

contains

  subroutine RestartFileOpen( flag_init_data )
    !
    ! リスタート/初期値ファイルをオープンします. 
    !
    ! A restart/initial data 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

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

    ! 文字列操作
    ! Character handling
    !
    use dc_string, only: 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(12):: time_unit
                              ! 日時の単位. Units of date and time

    logical:: flag_mpi_init

    ! 実行文 ; 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

    time_unit = IntUnit

    flag_mpi_init = .false.

    ! 軸データの設定
    ! Configure axes data
    !


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

    ! $ \Delta t $ に関する情報を追加. 
    ! Add information about $ \Delta t $. 
    !
    if ( .not. flag_init_data_save ) then
      call HistoryAddVariable( &
        & varname = 'deltime', &             ! (in)
        & dims = (/''/), &                   ! (in)
        & longname = 'delta time', &         ! (in)
        & units = 'sec', xtype = 'double', & ! (in)
        & history = gthst_rst )              ! (inout)
      call HistoryPut( &
        & varname = 'deltime', &            ! (in)
        & array = (/ DelTime /), &          ! (in)
        & history = gthst_rst )             ! (inout)
    end if

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

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

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

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

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

    ! 予報変数の設定
    ! Predictional variables settings
    !
    if ( flag_init_data_save ) then

      ! 初期データファイル用
      ! For initial data file
      !
      call HistoryAddVariable( 'U', &                         ! (in)
        & (/ 'lon ', 'lat ', 'sig ', 'time' /), &             ! (in)
        & 'eastward wind', 'm s-1', &                         ! (in)
        & xtype = 'double', &                                 ! (in)
        & history = gthst_rst )                               ! (inout)
      call HistoryAddVariable( 'V', &                         ! (in)
        & (/ 'lon ', 'lat ', 'sig ', 'time' /), &             ! (in)
        & 'northward wind', 'm s-1', &                        ! (in)
        & xtype = 'double', &                                 ! (in)
        & history = gthst_rst )                               ! (inout)
      call HistoryAddVariable( 'Temp', &                      ! (in)
        & (/ 'lon ', 'lat ', 'sig ', 'time' /), &             ! (in)
        & 'temperature', 'K', &                               ! (in)
        & xtype = 'double', &                                 ! (in)
        & history = gthst_rst )                               ! (inout)
      call HistoryAddVariable( 'QVap', &                      ! (in)
        & (/ 'lon ', 'lat ', 'sig ', 'time' /), &             ! (in)
        & 'specific humidity', 'kg kg-1', &                   ! (in)
        & xtype = 'double', &                                 ! (in)
        & history = gthst_rst )                               ! (inout)
      call HistoryAddVariable( 'Ps', &                        ! (in)
        & (/ 'lon ', 'lat ', 'time' /), &                     ! (in)
        & 'surface pressure', 'Pa', &                         ! (in)
        & xtype = 'double', &                                 ! (in)
        & history = gthst_rst )                               ! (inout)

    else
      ! リスタートデータファイル用
      ! For restart data file
      !
      call HistoryAddVariable( 'UB', &                        ! (in)
        & (/ 'lon ', 'lat ', 'sig ', 'time' /), &             ! (in)
        & 'eastward wind (at t-\Delta t)', 'm s-1', &         ! (in)
        & xtype = 'double', &                                 ! (in)
        & history = gthst_rst )                               ! (inout)
      call HistoryAddVariable( 'VB', &                        ! (in)
        & (/ 'lon ', 'lat ', 'sig ', 'time' /), &             ! (in)
        & 'northward wind (at t-\Delta t)', 'm s-1', &        ! (in)
        & xtype = 'double', &                                 ! (in)
        & history = gthst_rst )                               ! (inout)
      call HistoryAddVariable( 'TempB', &                     ! (in)
        & (/ 'lon ', 'lat ', 'sig ', 'time' /), &             ! (in)
        & 'temperature (at t-\Delta t)', 'K', &               ! (in)
        & xtype = 'double', &                                 ! (in)
        & history = gthst_rst )                               ! (inout)
      call HistoryAddVariable( 'QVapB', &                     ! (in)
        & (/ 'lon ', 'lat ', 'sig ', 'time' /), &             ! (in)
        & 'specific humidity (at t-\Delta t)', 'kg kg-1', &   ! (in)
        & xtype = 'double', &                                 ! (in)
        & history = gthst_rst )                               ! (inout)
      call HistoryAddVariable( 'PsB', &                       ! (in)
        & (/ 'lon ', 'lat ', 'time' /), &                     ! (in)
        & 'surface pressure (at t-\Delta t)', 'Pa', &         ! (in)
        & xtype = 'double', &                                 ! (in)
        & history = gthst_rst )                               ! (inout)

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

    restart_file_opened = .true.
  end subroutine RestartFileOpen

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

  subroutine RestartFileOutput0( &
    & 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
    !

    ! 時刻管理
    ! Time control
    !
    use timeset, only: &
      & TimeN, &              ! ステップ $ t $ の時刻. 
                              ! Time of step $ t $. 
      & EndTime               ! 計算終了時刻. 
                              ! End time of calculation

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

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

    ! 日付および時刻の取り扱い
    ! Date and time handler
    !
    use dc_date, only: operator(+), operator(<), operator(-), &
      & 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
    !
    logical:: flag_output
                              ! 出力のフラグ. 
                              ! Flag for output

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

    ! リスタートデータ出力であることのチェック
    ! Check restart data output
    !
    if ( flag_init_data_save ) then
      call MessageNotify( 'E', module_name, &
        & 'Now, initial data output mode.' )
    end if

    ! 出力タイミングのチェック
    ! Check output timing
    !
    flag_output = TimeN - PrevOutputTime >= IntTime
    if ( TimeN >= EndTime .and. .not. flag_output_end ) then
      flag_output = .true.
      flag_output_end = .true.
    end if
    flag_output = ( .not. TimeN == PrevOutputTime ) .and. flag_output
    flag_output = flag_init_data_save .or. flag_output

    if ( .not. flag_output ) return

    ! 次回用に, 今回の出力 (希望) 時刻 を保存
    ! Save output time (expected) in this time, for next time
    !
    PrevOutputTime = PrevOutputTime + IntTime

    ! 時刻の設定
    ! Set time
    !
    call HistorySetTime( difftime = TimeN, history = gthst_rst )

    ! データ出力
    ! 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 RestartFileOutput0

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

  subroutine InitialFileOutput( &
    & xyz_U, xyz_V, xyz_Temp, xyz_QVap, xy_Ps  &   ! (in)
    & )
    !
    ! 初期値データの出力を行います. 
    !
    ! Output initial data

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

    ! 時刻管理
    ! Time control
    !
    use timeset, only: &
      & TimeN, &              ! ステップ $ t $ の時刻. 
                              ! Time of step $ t $. 
      & EndTime               ! 計算終了時刻. 
                              ! End time of calculation

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

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

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

    ! 宣言文 ; Declaration statements
    !
    implicit none
    real(DP), intent(in):: xyz_U  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ u $ .     東西風速. Eastward wind
    real(DP), intent(in):: xyz_V  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ v $ .     南北風速. Northward wind
    real(DP), intent(in):: xyz_Temp  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ T $ .     温度. Temperature
    real(DP), intent(in):: xyz_QVap  (0:imax-1, 1:jmax, 1:kmax)
                              ! $ q $ .     比湿. Specific humidity
    real(DP), intent(in):: xy_Ps (0:imax-1, 1:jmax)
                              ! $ p_s $ .   地表面気圧. Surface pressure

    ! 実行文 ; Executable statement
    !
    if ( .not. restart_file_opened ) call RestartFileOpen( flag_init_data = .true. )

    ! 初期値出力であることのチェック
    ! Check initial data output
    !
    if ( .not. flag_init_data_save ) then
      call MessageNotify( 'E', module_name, &
        & 'Now, restart data output mode.' )
    end if

    ! 時刻の設定
    ! Set time
    !
    call HistorySetTime( difftime = TimeN, history = gthst_rst )

    ! データ出力
    ! Data output
    !
    call HistoryPut( &
      & 'U', xyz_U, history = gthst_rst )       ! (in)
    call HistoryPut( &
      & 'V', xyz_V, history = gthst_rst )       ! (in)
    call HistoryPut( &
      & 'Temp', xyz_Temp, history = gthst_rst ) ! (in)
    call HistoryPut( &
      & 'QVap', xyz_QVap, history = gthst_rst ) ! (in)
    call HistoryPut( &
      & 'Ps', xy_Ps, history = gthst_rst )      ! (in)

  end subroutine InitialFileOutput

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

  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/initial data. 
    ! If a restart/initial data file is not exist, 
    ! initial data is created by "initial_data". 


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

    ! 時刻管理
    ! Time control
    !
    use timeset, only: &
      & DelTime               ! $ \Delta t $ [s]

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

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

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

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

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

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

    ! 宣言文 ; 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
    !
    logical:: flag_init_get   ! 初期値データ入力時は .true. 
                              ! 
                              ! If initial data is input, 
                              ! this is ".true.".

    character(STRING):: time_range
                              ! 時刻の指定. 
                              ! Specification of time
    real(DP):: deltime_value
                              ! 'deltime' 変数の値. 
                              ! Value of 'deltime' variable. 
    real(DP):: time_check
                              ! 時刻チェック用作業変数
                              ! Work variable for check time
    character(TOKEN):: dummy_str
                              ! 入力チェック用のダミー変数
                              ! Dummy variable for check of input
    logical:: get_err
                              ! 入力時のエラーフラグ. 
                              ! Error flag for input
    real(DP):: returned_time
                              ! 入力データの時刻. 
                              ! Time of input data.
    character(TOKEN):: time_units
                              ! 入力データの時刻の単位. 
                              ! Units of time of input data.
    logical:: flag_time_exist
                              ! 入力データの時刻用のフラグ. 
                              ! Flag for time of input data.
    real(DP):: start_time
                              ! 計算開始時刻. 
                              ! Start time of calculation

    logical:: flag_mpi_init

    ! 実行文 ; Executable statement
    !

    if ( .not. restart_file_io_inited ) call RestartFileInit

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

      call MessageNotify( 'M', module_name, &
        & 'Initial data (not restart data) is input ' // &
        & 'from a module "initial_data". ' // &
        & '*B (t-dt) and *N (t) are same.' )

      xyz_UN    = xyz_UB
      xyz_VN    = xyz_VB
      xyz_TempN = xyz_TempB
      xyz_QVapN = xyz_QVapB
      xy_PsN    = xy_PsB

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

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

!!$      flag_mpi_init = .false.
      flag_mpi_init = .true.

      ! ファイルの有無を確認
      ! Conform an existence of an input file
      ! 
      call HistoryGetAttr( InputFile, 'lon', 'units', & ! (in)
        & dummy_str, &                                  ! (out)
        & flag_mpi_split = flag_mpi_init, &             ! (in) optional
        & err = get_err )                               ! (out)

      if ( get_err ) then
        call MessageNotify( 'E', module_name, &
          & 'restart/initial data file "%c" is not found.', &
          & c1 = trim(InputFile) )
      end if

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

      ! 初期値データかリスタートデータかのチェック
      ! Check whether input data is initial data or restart data
      ! 
      call HistoryGet( &
        & InputFile, 'U', &                       ! (in)
        & xyz_UB, &                               ! (out)
        & err = get_err, &                        ! (out) optional
        & quiet = .true., &                       ! (in) optional
        & flag_mpi_split = flag_mpi_init )        ! (in) optional

      if ( .not. get_err ) then
        flag_init_get = .true.
        if ( present(flag_initial) ) flag_initial = .true.

      else
        flag_init_get = .false.
        if ( present(flag_initial) ) flag_initial = .false.

        call HistoryGet( &
          & InputFile, 'UB', &                      ! (in)
          & xyz_UB, &                               ! (out)
          & range = time_range, &                   ! (in) optional
          & quiet = .true., &                       ! (in) optional
          & err = get_err, &                        ! (out) optional
          & returned_time = returned_time, &        ! (out) optional
          & flag_time_exist = flag_time_exist, &    ! (out) optional
          & flag_mpi_split = flag_mpi_init )        ! (in) optional

        if ( get_err ) then
          call MessageNotify( 'E', module_name, &
            & 'One of necessary variables "UB" for restart ' // &
            & 'is not included in "%c"', &
            & c1 = trim(InputFile) )
        end if

        ! 時間ステップのチェック
        ! Check time step
        !
        deltime_value = 0.
        call HistoryGet( &
          & InputFile, 'deltime', &     ! (in)
          & array = deltime_value, &    ! (out)
          & err = get_err )             ! (out)

        if ( get_err ) then
          call MessageNotify( 'E', module_name, &
            & 'A necessary variable "deltime" for restart ' // &
            & 'is not included in "%c"', &
            & c1 = trim(InputFile) )
        end if

        time_check = deltime_value / DelTime
        if ( 0.999 > time_check .or. time_check > 1.0001 ) then
          call MessageNotify( 'E', module_name, &
            & 'deltime=<%f> [sec] in "%c" is differ from DelTime=<%f> [sec]', &
            & c1 = trim(InputFile), d = (/deltime_value, DelTime/) )
        end if

        ! データの時刻とモデル時刻の比較
        ! Compare Time of data with model time
        !
        if ( .not. flag_time_exist ) then
          call MessageNotify( 'E', module_name, &
            & 'Input data does not depend on time. ' // &
            & 'Restart data must be depended on time. ' )
        end if

        call HistoryGetAttr( InputFile, 'time', 'units', & ! (in)
          & time_units, &                                  ! (out)
          & flag_mpi_split = flag_mpi_init )               ! (in) optional
        start_time = EvalByUnit( StartTime, time_units )

        if ( start_time == 0. ) then
          if ( .not. returned_time == 0. ) then
            call MessageNotify( 'E', module_name, &
              & 'time=<%f> [%c] of data in "%c" is differ from StartTime=<%f> [%c]', &
              & c1 = trim(time_units), c2 = trim(InputFile), c3 = trim(time_units), &
              & d = (/returned_time, start_time/) )
          end if
        else
          time_check = returned_time / start_time
          if ( 0.999 > time_check .or. time_check > 1.0001 ) then
            call MessageNotify( 'E', module_name, &
              & 'time=<%f> of data in "%c" is differ from StartTime=<%f>', &
              & c1 = trim(InputFile), d = (/returned_time, start_time/) )
          end if
        end if

      end if

      ! データ入力
      ! Data input
      ! 
      if ( flag_init_get ) then
        call HistoryGet( &
          & InputFile, 'U', &                 ! (in)
          & array = xyz_UB, &                 ! (out)
          & flag_mpi_split = flag_mpi_init )  ! (in) optional
        call HistoryGet( &
          & InputFile, 'V', &                 ! (in)
          & array = xyz_VB, &                 ! (out)
          & flag_mpi_split = flag_mpi_init )  ! (in) optional
        call HistoryGet( &
          & InputFile, 'Temp', &              ! (in)
          & array = xyz_TempB, &              ! (out)
          & flag_mpi_split = flag_mpi_init )  ! (in) optional
        call HistoryGet( &
          & InputFile, 'QVap', &              ! (in)
          & array = xyz_QVapB, &              ! (out)
          & flag_mpi_split = flag_mpi_init )  ! (in) optional
        call HistoryGet( &
          & InputFile, 'Ps', &                ! (in)
          & array = xy_PsB, &                 ! (out)
          & flag_mpi_split = flag_mpi_init )  ! (in) optional

        call MessageNotify( 'M', module_name, &
          & 'Initial data (not restart data) is input ' // &
          & 'from a data file "%c". ' // &
          & '*B (t-dt) and *N (t) are same.', &
          & c1 = trim(InputFile) )

        xyz_UN    = xyz_UB
        xyz_VN    = xyz_VB
        xyz_TempN = xyz_TempB
        xyz_QVapN = xyz_QVapB
        xy_PsN    = xy_PsB

      else
        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

        call MessageNotify( 'M', module_name, &
          & 'Restart data (not initial data) is input ' // &
          & 'from a data file "%c". ', &
          & c1 = trim(InputFile) )
      end if

    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 = 'rst.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

    ! フラグの初期化
    ! Initialize flag
    !
    flag_output_end = .false.

    ! 印字 ; Print
    !
    call MessageNotify( 'M', module_name, '----- Initialization Messages -----' )
    call MessageNotify( 'M', module_name, 'Input:: ' )
    if ( trim(InputFile) /= '' ) then
      call MessageNotify( 'M', module_name, '  InputFile  = %c', c1 = trim(InputFile) )
    else
      call MessageNotify( 'M', module_name, '  InputFile  = <Non>' )
      call MessageNotify( 'M', module_name, '  ** Initial data is generated in "initial_data" module' )
    end if
    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
