!= 地表面温度リスタートデータ, 初期値データ入出力
!
!= Restart data, initial data of surface temperature input/output
!
! Authors::   Yasuhiro Morikawa, Yoshiyuki O. Takahashi, Shin-ichi Takehiro
! Version::   $Id: restart_surftemp_io.f90,v 1.11 2025/09/17 22:00:00 takepiro Exp $
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2008-2025. All rights reserved.
! License::   See COPYRIGHT[link:../../../COPYRIGHT]
!

module restart_surftemp_io
  !
  != 地表面温度リスタートデータ, 初期値データ入出力
  !
  != Restart data, initial data of surface temperature input/output
  !
  ! <b>Note that Japanese and English are described in parallel.</b>
  !
  ! 地表面温度のリスタートデータもしくは初期値データの入出力を行います. 
  ! 入力ファイル, 出力ファイル, データの出力の間隔は
  ! NAMELIST#restart_surftemp_io_nml で設定します. 
  !
  ! リスタートデータの入力ファイルが指定されない場合, 
  ! surface_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_surftemp_io_nml". 
  !
  ! If input file of restart data is not set, 
  ! initial data is generated in "surface_data" module, and 
  ! obtained data from the module. 
  !
  !== Procedures List
  !
  ! RestartSurfTempOpen   :: リスタートファイルのオープン
  ! RestartSurfTempOutput :: リスタートファイルへのデータ出力
  ! RestartSurfTempClose  :: リスタートファイルのクローズ
  ! RestartSurfTempGet    :: リスタートファイルの入力
  ! ------------      :: ------------
  ! RestartSurfTempOpen   :: Open restart file
  ! RestartSurfTempOutput :: Data output to restart file
  ! RestartSurfTempClose  :: Close restart file
  ! RestartSurfTempGet    :: Input restart file
  !
  !== NAMELIST
  !
  ! NAMELIST#restart_surftemp_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
    &                kslmax, & ! 地下の鉛直層数.
                               ! Number of subsurface vertical level
    &                ksimax    ! 海氷の鉛直層数.
                               ! Number of sea ice vertical level

  ! 種別型パラメタ
  ! 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 :: RestartSurfTempInit
  public :: RestartSurfTempOpen, RestartSurfTempClose, RestartSurfTempOutPut
  public :: RestartSurfTempGet

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

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

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

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

  ! This is not used, and variable name is fixed, 'SurfTemp' (yot, 2011/09/10).
!!$  character(TOKEN), save:: InputName
!!$                              ! 入力するリスタートデータの変数名
!!$                              ! Variable name of input restart data

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

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

  real(DP), save:: PrevOutputTime
                              ! 前回の出力時間. 
                              ! Previous output time
  logical, save:: flag_output_end
                              ! 計算最終時刻の出力完了のフラグ. 
                              ! Flag for completion of output at the end time of calculation

  real(DP), 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_surftemp_io'
                              ! モジュールの名称. 
                              ! Module name
  character(*), parameter:: version = &
    & '$Name:  $' // &
    & '$Id: restart_surftemp_io.f90,v 1.11 2025/09/17 22:00:00 takepiro Exp $'
                              ! モジュールのバージョン
                              ! Module version

contains

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

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

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

    ! MPI
    !
    use mpi_wrapper, only : flag_mpi_init

    ! 出力ファイルの基本情報
    ! 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 and mathematical constants settings
    !
    use constants0, 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_SSDepth, &
                              ! 地下の格子点の深さ
                              ! subsurface grid at midpoint of layer
      & z_SIDepth
                              ! 海氷の格子点の深さ
                              ! sea ice grid at midpoint of layer

    ! 時刻管理
    ! Time control
    !
    use timeset, only: &
      & RestartTime           ! リスタート開始時刻. 
                              ! Retart time of calculation

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

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

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

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

    ! 作業変数
    ! Work variables
    !
    integer                       :: NDims
    character(STRING), allocatable:: a_DimNames    (:)
    integer          , allocatable:: a_DimLens     (:)
    character(STRING), allocatable:: a_DimLongNames(:)
    character(STRING), allocatable:: a_DimUnits    (:)

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

    integer:: n


    ! 実行文 ; Executable statement
    !

    ! 初期化
    ! Initialization
    !
    flag_init_data_save = present_and_true( flag_init_data )
    if ( .not. restart_surftemp_io_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if
    if ( restart_surftemp_opened ) return

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

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

    time_unit = IntUnit

    ! リスタートファイルのオープン
    ! Open a restart file
    !
    n = 3                              ! lon, lat, time
    if ( kslmax /= 0 ) n = n + 1       ! dep
    if ( ksimax /= 0 ) n = n + 1       ! sidep
    NDims = n
    !
    allocate( a_DimNames    ( 1:NDims ) )
    allocate( a_DimLens     ( 1:NDims ) )
    allocate( a_DimLongNames( 1:NDims ) )
    allocate( a_DimUnits    ( 1:NDims ) )
    !
    n = 1 ! lon
    a_DimNames    (n) = 'lon'
    a_DimLens     (n) = imax
    a_DimLongNames(n) = 'longitude'
    a_DimUnits    (n) = 'degrees_east'
    n = n + 1 ! lat
    a_DimNames    (n) = 'lat'
    a_DimLens     (n) = jmax
    a_DimLongNames(n) = 'latitude'
    a_DimUnits    (n) = 'degrees_north'
    if ( kslmax /= 0 ) then
      n = n + 1 ! dep
      a_DimNames    (n) = 'dep'
      a_DimLens     (n) = kslmax
      a_DimLongNames(n) = 'depth'
      a_DimUnits    (n) = 'm'
    end if
    if ( ksimax /= 0 ) then
      n = n + 1 ! sidep
      a_DimNames    (n) = 'sidep'
      a_DimLens     (n) = ksimax
      a_DimLongNames(n) = 'depth'
      a_DimUnits    (n) = 'm'
    end if
    n = n + 1 ! time
    a_DimNames    (n) = time_name
    a_DimLens     (n) = 0
    a_DimLongNames(n) = time_name
    a_DimUnits    (n) = time_unit
    !
!!$    call HistoryCreate(                                                     &
!!$      &      file = OutputFile,                                             &  ! (in)
!!$      &     title = trim(FileTitle) // trim(title_msg),                     &  ! (in)
!!$      &    source = FileSource, institution = FileInstitution,              &  ! (in)
!!$      &      dims = StoA( 'lon  ', 'lat  ', 'dep  ', 'sidep', time_name ),  &  ! (in)
!!$      &  dimsizes = (/ imax, jmax, kslmax, ksimax, 0 /),                    &  ! (in)
!!$      & longnames = StoA( 'longitude', 'latitude', 'depth   ', 'depth   ', time_name ), &  ! (in)
!!$      &     units = StoA( 'degrees_east', 'degrees_north', 'm            ', 'm            ', &  ! (in)
!!$      &                    time_unit ),                                     &  ! (in)
!!$      &        origind = origin_time,                                       &  ! (in) optional
!!$      &      intervald = IntValue,                                          &  ! (in) optional
!!$      & flag_mpi_split = flag_mpi_init,                                     &  ! (in) optional
!!$      &        history = gthst_rst                                          &  ! (out) optional
!!$      & )
    call HistoryCreate(                                        &
      &      file = OutputFile,                                &  ! (in)
      &     title = trim(FileTitle) // trim(title_msg),        &  ! (in)
      &    source = FileSource, institution = FileInstitution, &  ! (in)
      &      dims = a_DimNames,                                &  ! (in)
      &  dimsizes = a_DimLens,                                 &  ! (in)
      & longnames = a_DimLongNames,                            &  ! (in)
      &     units = a_DimUnits,                                &  ! (in)
      &        origind = origin_time,                          &  ! (in) optional
      &      intervald = IntValue,                             &  ! (in) optional
      & flag_mpi_split = flag_mpi_init,                        &  ! (in) optional
      &        history = gthst_rst                             &  ! (out) optional
      & )
    !
    deallocate( a_DimNames     )
    deallocate( a_DimLens      )
    deallocate( a_DimLongNames )
    deallocate( a_DimUnits     )

    ! 座標データの設定
    ! 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)
      & )
    if ( kslmax /= 0 ) then
      call HistoryAddAttr(                                 &
        & varname = 'dep', attrname = 'standard_name',     & ! (in)
        & value = 'depth',                                 & ! (in)
        & history = gthst_rst                              & ! (inout)
        & )
    end if
    if ( ksimax /= 0 ) then
      call HistoryAddAttr(                                 &
        & varname = 'sidep', attrname = 'standard_name',   & ! (in)
        & value = 'depth',                                 & ! (in)
        & history = gthst_rst                              & ! (inout)
        & )
    end if
    call HistoryAddAttr(                                 &
      & varname = time_name, attrname = 'standard_name', & ! (in)
      & value = 'time',                                  & ! (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)
      & )
    if ( kslmax /= 0 ) then
      call HistoryPut(                   &
        & varname = 'dep',               & ! (in)
        & array = z_SSDepth,             & ! (in)
        & history = gthst_rst            & ! (inout)
        & )
    end if
    if ( ksimax /= 0 ) then
      call HistoryPut(                   &
        & varname = 'sidep',             & ! (in)
        & array = z_SIDepth,             & ! (in)
        & history = gthst_rst            & ! (inout)
        & )
    end if

    ! 座標重みの設定
    ! 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)

    ! 予報変数の設定
    ! Predictional variables settings
    !
    call HistoryAddVariable(                  &
      & varname = 'SurfTemp',                 & ! (in)
      & dims = StoA('lon', 'lat', time_name), & ! (in)
      & longname = 'surface temperature',     & ! (in)
      & units = 'K', xtype = 'double',        & ! (in)
      & history = gthst_rst                   & ! (inout)
      & )
    if ( kslmax /= 0 ) then
      call HistoryAddVariable(                         &
        & varname = 'SoilTemp',                        & ! (in)
        & dims = StoA('lon', 'lat', 'dep', time_name), & ! (in)
        & longname = 'soil temperature',               & ! (in)
        & units = 'K', xtype = 'double',               & ! (in)
        & history = gthst_rst                          & ! (inout)
        & )
    end if
    if ( ksimax /= 0 ) then
      call HistoryAddVariable(                           &
        & varname = 'SOSeaIceTemp',                      & ! (in)
        & dims = StoA('lon', 'lat', 'sidep', time_name), & ! (in)
        & longname = 'sea ice temperature',              & ! (in)
        & units = 'K', xtype = 'double',                 & ! (in)
        & history = gthst_rst                            & ! (inout)
        & )
    end if
    call HistoryAddVariable(                     &
      & varname = 'SOSeaIceMass',                & ! (in)
      & dims = StoA('lon', 'lat', time_name),    & ! (in)
      & longname = 'slab sea ice mass',          & ! (in)
      & units = 'kg m-2', xtype = 'double',      & ! (in)
      & history = gthst_rst                      & ! (inout)
      & )
    call HistoryAddVariable(                  &
      & varname = 'SurfMajCompIceB',          & ! (in)
      & dims = StoA('lon', 'lat', time_name), & ! (in)
      & longname = 'major component ice amount on the surface', & ! (in)
      & units = 'kg m-2', xtype = 'double',   & ! (in)
      & history = gthst_rst                   & ! (inout)
      & )
    call HistoryAddVariable(                  &
      & varname = 'SoilMoistB',               & ! (in)
      & dims = StoA('lon', 'lat', time_name), & ! (in)
      & longname = 'soil moisture',           & ! (in)
      & units = 'kg m-2', xtype = 'double',   & ! (in)
      & history = gthst_rst                   & ! (inout)
      & )
    call HistoryAddVariable(                     &
      & varname = 'SurfSnowB',                   & ! (in)
      & dims = StoA('lon', 'lat', time_name),    & ! (in)
      & longname = 'snow amount on the surface', & ! (in)
      & units = 'kg m-2', xtype = 'double',      & ! (in)
      & history = gthst_rst                      & ! (inout)
      & )
    call HistoryAddVariable(                  &
      & varname = 'SurfMajCompIceN',          & ! (in)
      & dims = StoA('lon', 'lat', time_name), & ! (in)
      & longname = 'major component ice amount on the surface', & ! (in)
      & units = 'kg m-2', xtype = 'double',   & ! (in)
      & history = gthst_rst                   & ! (inout)
      & )
    call HistoryAddVariable(                  &
      & varname = 'SoilMoistN',               & ! (in)
      & dims = StoA('lon', 'lat', time_name), & ! (in)
      & longname = 'soil moisture',           & ! (in)
      & units = 'kg m-2', xtype = 'double',   & ! (in)
      & history = gthst_rst                   & ! (inout)
      & )
    call HistoryAddVariable(                     &
      & varname = 'SurfSnowN',                   & ! (in)
      & dims = StoA('lon', 'lat', time_name),    & ! (in)
      & longname = 'snow amount on the surface', & ! (in)
      & units = 'kg m-2', xtype = 'double',      & ! (in)
      & history = gthst_rst                      & ! (inout)
      & )

    restart_surftemp_opened = .true.
  end subroutine RestartSurfTempOpen

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

  subroutine RestartSurfTempOutput(                    &
    & xy_SurfTemp,                                     & ! (in)
    & xyz_SoilTemp,                                    & ! (in) optional
    & xyz_SOSeaIceTemp, xy_SOSeaIceMass,               & ! (in) optional
    & xy_SurfMajCompIceB, xy_SoilMoistB, xy_SurfSnowB, & ! (in) optional
    & xy_SurfMajCompIceN, xy_SoilMoistN, xy_SurfSnowN  & ! (in) optional
    & )
    !
    ! リスタートデータの出力を行います. 
    !
    ! Output restart data

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

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

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

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

    ! 宣言文 ; Declaration statements
    !
    real(DP), intent(in)           :: xy_SurfTemp (0:imax-1, 1:jmax)
                              ! 地表面温度. 
                              ! Surface temperature
    real(DP), intent(in), optional :: xyz_SoilTemp      (0:imax-1, 1:jmax, 1:kslmax)
    real(DP), intent(in), optional :: xyz_SOSeaIceTemp  (0:imax-1, 1:jmax, 1:ksimax)
    real(DP), intent(in), optional :: xy_SOSeaIceMass   (0:imax-1, 1:jmax)
    real(DP), intent(in), optional :: xy_SurfMajCompIceB(0:imax-1, 1:jmax)
    real(DP), intent(in), optional :: xy_SoilMoistB     (0:imax-1, 1:jmax)
    real(DP), intent(in), optional :: xy_SurfSnowB      (0:imax-1, 1:jmax)
    real(DP), intent(in), optional :: xy_SurfMajCompIceN(0:imax-1, 1:jmax)
    real(DP), intent(in), optional :: xy_SoilMoistN     (0:imax-1, 1:jmax)
    real(DP), intent(in), optional :: xy_SurfSnowN      (0:imax-1, 1:jmax)

    ! 作業変数
    ! Work variables
    !
    logical:: flag_output
                              ! 出力のフラグ. 
                              ! Flag for output

    ! 実行文 ; Executable statement
    !

    if ( .not. restart_surftemp_opened ) call RestartSurfTempOpen

    ! 出力タイミングのチェック
    ! 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( timed = TimeN, history = gthst_rst )

    ! データ出力
    ! Data output
    !
    call HistoryPut( 'SurfTemp'  , xy_SurfTemp  , history = gthst_rst ) ! (in)
    if ( present( xyz_SoilTemp ) ) then
      if ( kslmax /= 0 ) then
        call HistoryPut( 'SoilTemp'  , xyz_SoilTemp , history = gthst_rst ) ! (in)
      end if
    end if
    if ( present( xyz_SOSeaIceTemp ) ) then
      if ( ksimax /= 0 ) then
        call HistoryPut( 'SOSeaIceTemp'  , xyz_SOSeaIceTemp , history = gthst_rst ) ! (in)
      end if
    end if
    if ( present( xy_SOSeaIceMass ) ) then
      call HistoryPut( 'SOSeaIceMass' , xy_SOSeaIceMass , history = gthst_rst ) ! (in)
    end if
    if ( present( xy_SurfMajCompIceB ) ) then
      call HistoryPut( 'SurfMajCompIceB', xy_SurfMajCompIceB, history = gthst_rst ) ! (in)
    end if
    if ( present( xy_SoilMoistB ) ) then
      call HistoryPut( 'SoilMoistB', xy_SoilMoistB, history = gthst_rst ) ! (in)
    end if
    if ( present( xy_SurfSnowB ) ) then
      call HistoryPut( 'SurfSnowB' , xy_SurfSnowB , history = gthst_rst ) ! (in)
    end if
    if ( present( xy_SurfMajCompIceN ) ) then
      call HistoryPut( 'SurfMajCompIceN', xy_SurfMajCompIceN, history = gthst_rst ) ! (in)
    end if
    if ( present( xy_SoilMoistN ) ) then
      call HistoryPut( 'SoilMoistN', xy_SoilMoistN, history = gthst_rst ) ! (in)
    end if
    if ( present( xy_SurfSnowN ) ) then
      call HistoryPut( 'SurfSnowN' , xy_SurfSnowN , history = gthst_rst ) ! (in)
    end if

  end subroutine RestartSurfTempOutput

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

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

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

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

    ! 宣言文 ; Declaration statements
    !

    ! 作業変数
    ! Work variables
    !

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

    call HistoryClose( history = gthst_rst ) ! (inout)

    restart_surftemp_opened = .false.
  end subroutine RestartSurfTempClose

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

  subroutine RestartSurfTempGet(                       &
    & xy_SurfTemp,                                     & ! (out)
    & xyz_SoilTemp,                                    & ! (out)
    & xyz_SOSeaIceTemp, xy_SOSeaIceMass,               & ! (out)
    & xy_SurfMajCompIceB, xy_SoilMoistB, xy_SurfSnowB, & ! (out)
    & xy_SurfMajCompIceN, xy_SoilMoistN, xy_SurfSnowN  & ! (out)
    & )
    !
    ! リスタートデータの入力を行います. 
    ! リスタートデータが存在しない場合には, 
    ! surface_data モジュールを用いて, 地表面温度データ生成を行います. 
    !
    ! Input restart data. 
    ! If restart data is not exist, 
    ! surface temperature data is created by "surface_data". 


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

    ! MPI
    !
    use mpi_wrapper, only : flag_mpi_init

    ! 地表面データ提供
    ! Prepare surface data
    !
    use surface_data, only: SetSurfData

    ! 時刻管理
    ! Time control
    !
    use timeset, only: &
      & RestartTime           ! リスタート開始時刻. 
                              ! Retart time of calculation

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

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

    ! NetCDF のラッパープログラム
    ! NetCDF wrapper
    !
    use netcdf_wrapper, only: NWPresentAVarInFile


    ! 宣言文 ; Declaration statements
    !
    real(DP), intent(out) :: xy_SurfTemp (0:imax-1, 1:jmax)
                              ! 地表面温度. 
                              ! Surface temperature
    real(DP), intent(out) :: xyz_SoilTemp (0:imax-1, 1:jmax, 1:kslmax)
    real(DP), intent(out) :: xyz_SOSeaIceTemp  (0:imax-1, 1:jmax, 1:ksimax)
    real(DP), intent(out) :: xy_SOSeaIceMass   (0:imax-1, 1:jmax)
    real(DP), intent(out) :: xy_SurfMajCompIceB(0:imax-1, 1:jmax)
    real(DP), intent(out) :: xy_SoilMoistB     (0:imax-1, 1:jmax)
    real(DP), intent(out) :: xy_SurfSnowB      (0:imax-1, 1:jmax)
    real(DP), intent(out) :: xy_SurfMajCompIceN(0:imax-1, 1:jmax)
    real(DP), intent(out) :: xy_SoilMoistN     (0:imax-1, 1:jmax)
    real(DP), intent(out) :: xy_SurfSnowN      (0:imax-1, 1:jmax)


    ! 作業変数
    ! Work variables
    !
    character(TOKEN) :: time_range
                              ! 時刻の指定. 
                              ! Specification of time
    integer          :: k

    ! 実行文 ; Executable statement
    !

    if ( .not. restart_surftemp_io_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if

    ! The variable name is fixed, 'SurfTemp' (yot, 2011/09/10).
!!$    if ( trim(InputFile) == '' .or. trim(InputName) == '' ) then
    if ( trim(InputFile) == '' ) then

      ! データを surface_data モジュールから取得
      ! Data is input from "surface_data" module
      !
      call SetSurfData( xy_SurfTemp = xy_SurfTemp )  ! (out) optional

      do k = 1, kslmax
        xyz_SoilTemp(:,:,k) = xy_SurfTemp
      end do

      do k = 1, ksimax
        xyz_SOSeaIceTemp(:,:,k) = xy_SurfTemp
      end do
      xy_SOSeaIceMass = 0.0_DP

      xy_SurfMajCompIceB = 0.0_DP
      xy_SoilMoistB      = 0.0_DP
      xy_SurfSnowB       = 0.0_DP

      xy_SurfMajCompIceN = xy_SurfMajCompIceB
      xy_SoilMoistN      = xy_SoilMoistB
      xy_SurfSnowN       = xy_SurfSnowB

    else

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

      ! 時刻情報の取得
      ! Get time information
      !
      time_range = time_name // '=' // toChar( RestartTime )

      ! データ入力
      ! Data input
      ! 
      call HistoryGet(                               &
        ! The variable name is fixed, 'SurfTemp' (yot, 2011/09/10).
!!$        & InputFile, InputName, range = time_range, &  ! (in)
        & InputFile, 'SurfTemp', range = time_range, & ! (in)
        & array = xy_SurfTemp,                       & ! (out)
        & flag_mpi_split = flag_mpi_init             & ! (in) optional
        & )
      if ( kslmax /= 0 ) then
        if ( NWPresentAVarInFile( InputFile, 'SoilTemp' ) ) then
          call HistoryGet(                               &
            & InputFile, 'SoilTemp', range = time_range, & ! (in)
            & array = xyz_SoilTemp,                      & ! (out)
            & flag_mpi_split = flag_mpi_init             & ! (in) optional
            & )
        else
          do k = 1, kslmax
            xyz_SoilTemp(:,:,k) = xy_SurfTemp
          end do
          call MessageNotify( 'M', module_name,             &
            & 'Variable, %c, cannot be found in file, %c.', &
            & c1 = 'SoilTemp', c2 = trim(InputFile)         &
            & )
          call MessageNotify( 'M', module_name,                           &
            & 'Values in SoilTemp is assumed to be the same as SurfTemp.' &
            & )
        end if
      end if
      if ( ksimax /= 0 ) then
        if ( NWPresentAVarInFile( InputFile, 'SOSeaIceTemp' ) ) then
          call HistoryGet(                                   &
            & InputFile, 'SOSeaIceTemp', range = time_range, & ! (in)
            & array = xyz_SOSeaIceTemp,                      & ! (out)
            & flag_mpi_split = flag_mpi_init                 & ! (in) optional
            & )
        else
          do k = 1, ksimax
            xyz_SOSeaIceTemp(:,:,k) = xy_SurfTemp
          end do
          call MessageNotify( 'M', module_name,             &
            & 'Variable, %c, cannot be found in file, %c.', &
            & c1 = 'SOSeaIceTemp', c2 = trim(InputFile)     &
            & )
          call MessageNotify( 'M', module_name,                           &
            & 'Values in SOSeaIceTemp is assumed to be the same as SurfTemp.' &
            & )
        end if
      end if
      if ( NWPresentAVarInFile( InputFile, 'SOSeaIceMass' ) ) then
        call HistoryGet(                                     &
          & InputFile, 'SOSeaIceMass', range = time_range,   & ! (in)
          & array = xy_SOSeaIceMass,                         & ! (out)
          & flag_mpi_split = flag_mpi_init                   & ! (in) optional
          & )
      else
        xy_SOSeaIceMass = 0.0_DP
        call MessageNotify( 'M', module_name,             &
          & 'Variable, %c, cannot be found in file, %c.', &
          & c1 = 'SOSeaIceMass', c2 = trim(InputFile)     &
          & )
        call MessageNotify( 'M', module_name,                &
          & 'Values in SOSeaIceMass is assumed to be zero.'  &
          & )
      end if
      if ( NWPresentAVarInFile( InputFile, 'SurfMajCompIceB' ) ) then
        call HistoryGet(                                      &
          & InputFile, 'SurfMajCompIceB', range = time_range, & ! (in)
          & array = xy_SurfMajCompIceB,                       & ! (out)
          & flag_mpi_split = flag_mpi_init                    & ! (in) optional
          & )
      else
        xy_SurfMajCompIceB = 0.0_DP
        call MessageNotify( 'M', module_name,             &
          & 'Variable, %c, cannot be found in file, %c.', &
          & c1 = 'SurfMajCompIceB', c2 = trim(InputFile)  &
          & )
        call MessageNotify( 'M', module_name,                  &
          & 'Values in SurfMajCompIceB is assumed to be zero.' &
          & )
      end if
      if ( NWPresentAVarInFile( InputFile, 'SoilMoistB' ) ) then
        call HistoryGet(                                 &
          & InputFile, 'SoilMoistB', range = time_range, & ! (in)
          & array = xy_SoilMoistB,                       & ! (out)
          & flag_mpi_split = flag_mpi_init               & ! (in) optional
          & )
      else
        xy_SoilMoistB = 0.0_DP
        call MessageNotify( 'M', module_name,             &
          & 'Variable, %c, cannot be found in file, %c.', &
          & c1 = 'SoilMoistB', c2 = trim(InputFile)       &
          & )
        call MessageNotify( 'M', module_name,             &
          & 'Values in SoilMoistB is assumed to be zero.' &
          & )
      end if
      if ( NWPresentAVarInFile( InputFile, 'SurfSnowB' ) ) then
        call HistoryGet(                                 &
          & InputFile, 'SurfSnowB', range = time_range,  & ! (in)
          & array = xy_SurfSnowB,                        & ! (out)
          & flag_mpi_split = flag_mpi_init               & ! (in) optional
          & )
      else
        xy_SurfSnowB = 0.0_DP
        call MessageNotify( 'M', module_name,             &
          & 'Variable, %c, cannot be found in file, %c.', &
          & c1 = 'SurfSnowB', c2 = trim(InputFile)        &
          & )
        call MessageNotify( 'M', module_name,             &
          & 'Values in SurfSnowB is assumed to be zero.'  &
          & )
      end if
      if ( NWPresentAVarInFile( InputFile, 'SurfMajCompIceN' ) ) then
        call HistoryGet(                                      &
          & InputFile, 'SurfMajCompIceN', range = time_range, & ! (in)
          & array = xy_SurfMajCompIceN,                       & ! (out)
          & flag_mpi_split = flag_mpi_init                    & ! (in) optional
          & )
      else
        xy_SurfMajCompIceN = xy_SurfMajCompIceB
        call MessageNotify( 'M', module_name,             &
          & 'Variable, %c, cannot be found in file, %c.', &
          & c1 = 'SurfMajCompIceN', c2 = trim(InputFile)  &
          & )
        call MessageNotify( 'M', module_name,                                         &
          & 'Values in SurfMajCompIceN is assumed to be the same as SurfMajCompIceB.' &
          & )
      end if
      if ( NWPresentAVarInFile( InputFile, 'SoilMoistN' ) ) then
        call HistoryGet(                                 &
          & InputFile, 'SoilMoistN', range = time_range, & ! (in)
          & array = xy_SoilMoistN,                       & ! (out)
          & flag_mpi_split = flag_mpi_init               & ! (in) optional
          & )
      else
        xy_SoilMoistN = xy_SoilMoistB
        call MessageNotify( 'M', module_name,             &
          & 'Variable, %c, cannot be found in file, %c.', &
          & c1 = 'SoilMoistN', c2 = trim(InputFile)       &
          & )
        call MessageNotify( 'M', module_name,                               &
          & 'Values in SoilMoistN is assumed to be the same as SoilMoistB.' &
          & )
      end if
      if ( NWPresentAVarInFile( InputFile, 'SurfSnowN' ) ) then
        call HistoryGet(                                 &
          & InputFile, 'SurfSnowN', range = time_range,  & ! (in)
          & array = xy_SurfSnowN,                        & ! (out)
          & flag_mpi_split = flag_mpi_init               & ! (in) optional
          & )
      else
        xy_SurfSnowN = xy_SurfSnowB
        call MessageNotify( 'M', module_name,             &
          & 'Variable, %c, cannot be found in file, %c.', &
          & c1 = 'SurfSnowN', c2 = trim(InputFile)        &
          & )
        call MessageNotify( 'M', module_name,                             &
          & 'Values in SurfSnowN is assumed to be the same as SurfSnowB.' &
          & )
      end if

    end if

  end subroutine RestartSurfTempGet

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

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

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

    ! リスタートデータ入出力
    ! Restart data input/output
    !
    use restart_file_io, only: restart_file_io_inited, &
      & RestartFileIntValue => IntValue, &
                              ! リスタートデータの出力間隔. 
                              ! Interval of restart data output
      & RestartFileIntUnit  => IntUnit
                              ! リスタートデータの出力間隔の単位. 
                              ! Unit for interval of restart data output

    ! 時刻管理
    ! Time control
    !
    use timeset, only: &
      & RestartTime           ! リスタート開始時刻. 
                              ! Retart time of calculation

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

    ! 暦と日時の取り扱い
    ! Calendar and Date handler
    !
    use dc_calendar, only: DCCalConvertByUnit

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

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

    ! メッセージ制御
    ! Message control
    !
    use mpi_messagecntl, only : DoesOutputMPIMessage

    
    ! 宣言文 ; Declaration statements
    !

    ! 作業変数
    ! 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_surftemp_io_nml/ &
      & InputFile, &
      ! The variable name is fixed, 'SurfTemp' (yot, 2011/09/10).
!!$      & InputName, &
      & OutputFile, &
      & IntValue, IntUnit
          !
          ! デフォルト値については初期化手続 "restart_surftemp_io#RestartSurfTempInit" 
          ! のソースコードを参照のこと. 
          !
          ! Refer to source codes in the initialization procedure
          ! "restart_surftemp_io#RestartSurfTempInit" for the default values. 
          !


    ! 実行文 ; Executable statement
    !

    if ( restart_surftemp_io_inited ) return


    ! デフォルト値の設定
    ! Default values settings
    !
    InputFile  = ''
    ! The variable name is fixed, 'SurfTemp' (yot, 2011/09/10).
!!$    InputName  = 'SurfTemp'
    if ( .not. flag_init_data_save ) then
      OutputFile = 'rst_sst.nc'
    else
      OutputFile = 'sst.nc'
    end if

    if ( restart_file_io_inited ) then
      IntValue   = RestartFileIntValue
      IntUnit    = RestartFileIntUnit
    else
      IntValue   = 365.0_DP
      IntUnit    = 'day'
    end if

    ! 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_surftemp_io_nml, &  ! (out)
        & iostat = iostat_nml ) ! (out)
      close( unit_nml )

      call NmlutilMsg( iostat_nml, module_name ) ! (in)
      if ( iostat_nml == 0 .AND. DoesOutputMPIMessage() ) write( STDOUT, nml = restart_surftemp_io_nml )
    end if

    ! 出力時間間隔の設定
    ! Configure time interval of output
    !
    IntTime = DCCalConvertByUnit( IntValue, IntUnit, 'sec' ) ! (in)
    PrevOutputTime = RestartTime

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


    ! 印字 ; Print
    !
    call MessageNotify( 'M', module_name, '----- Initialization Messages -----' )
    call MessageNotify( 'M', module_name, 'Input:: ' )
    call MessageNotify( 'M', module_name, '  InputFile  = %c', c1 = trim(InputFile) )
    ! The variable name is fixed, 'SurfTemp' (yot, 2011/09/10).
!!$    call MessageNotify( 'M', module_name, '  InputName  = %c', c1 = trim(InputName) )
    call MessageNotify( 'M', module_name, 'Output:: ' )
    call MessageNotify( 'M', module_name, '  OutputFile = %c', c1 = trim(OutputFile) )
    call MessageNotify( 'M', module_name, '  IntTime    = %f [%c]', d = (/ IntValue /), c1 = trim(IntUnit) )
    call MessageNotify( 'M', module_name, '-- version = %c', c1 = trim(version) )

    restart_surftemp_io_inited = .true.

  end subroutine RestartSurfTempInit

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

end module restart_surftemp_io
