!= dcpam 主プログラム
!
!= dcpam main program
!
! Authors::   Yasuhiro Morikawa, Satoshi Noda, Yoshiyuki O. Takahashi, Shin-ichi Takehiro
! Version::   $Id: dcpam_main_hs94.f90,v 1.67 2025/09/18 11:00:00 takepiro Exp $ 
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2008-2025. All rights reserved.
! License::   See COPYRIGHT[link:../../../COPYRIGHT]
!

program dcpam_main_hs94
  !
  ! <b>Note that Japanese and English are described in parallel.</b>
  !
  ! モデルの使い方については {チュートリアル}[link:../../../doc/tutorial/rakuraku/] を
  ! 参照してください.
  !
  ! See {Tutorial}[link:../../../doc/tutorial/rakuraku/index.htm.en] for usage of the 
  ! model. 
  !

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

  ! 力学過程 (スペクトル法, Arakawa and Suarez (1983))
  ! Dynamical process (Spectral method, Arakawa and Suarez (1983))
  !
  use dynamics_hspl_vas83, only: DynamicsHsplVAS83

  ! Held and Suarez (1994) による強制と散逸
  ! Forcing and dissipation suggested by Held and Suarez (1994)
  !
  use held_suarez_1994, only: HS94Forcing

  ! タイムフィルター (Asselin, 1972)
  ! Time filter (Asselin, 1972)
  !
  use timefilter_asselin1972, only: TimeFilter, TimeFilterSurfVars

  ! 時間フィルター (Williams, 2009)
  ! Time filter (Williams, 2009)
  !
  use timefilter_williams2009, only: &
    & TimeFilterWilliams2009, TimeFilterWilliams2009SurfVars

  ! 時刻管理
  ! Time control
  !
  use timeset, only: TimesetProgress, &
    & TimeB, &                ! ステップ $ t - \Delta t $ の時刻. 
                              ! Time of step $ t - \Delta t $. 
    & TimeN, &                ! ステップ $ t $ の時刻. 
                              ! Time of step $ t $. 
    & TimeA, &                ! ステップ $ t + \Delta t $ の時刻. 
                              ! Time of step $ t + \Delta t $. 
    & EndTime, &              ! 計算終了時刻. 
                              ! End time of calculation
    & DelTime                 ! $ \Delta t $ [s]

  ! リスタートデータ入出力
  ! Restart data input/output
  !
  use restart_file_io, only: RestartFileOutPut

  ! ヒストリデータ出力
  ! History data output
  !
  use gtool_historyauto, only: HistoryAutoPut, HistoryAutoAllVarFix

  ! 組成に関わる配列の設定
  ! Settings of array for atmospheric composition
  !
  use composition, only: &
    &                    ncmax, &
                              ! 成分の数
                              ! Number of composition
    &                    a_QMixName, &
                              ! 成分の変数名
                              ! Name of variables for composition
    &                    a_QMixLongName, &
                              ! 成分の長い変数名
                              ! Long name of variables for composition
    &                    IndexH2OVap, &
    &                    IndexH2OLiq, &
    &                    IndexH2OSol, &
    &                    IndexTKE,    &
    &                    CompositionInqIndex


  ! 格子点設定
  ! 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

  ! 物理定数設定
  ! Physical constants settings
  !
  use constants, only:  &
    & LatentHeat      , &
    & LatentHeatFusion, &
    & Grav
                              ! $ g $ [m s-2]. 
                              ! 重力加速度. 
                              ! Gravitational acceleration

  !
  !
  use dc_message, only: MessageNotify

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

  ! 予報変数の値の確認
  ! Check values of prognostic variables
  !
  use check_prog_vars, only: CheckProgVars

  ! Output frequently used variables
  ! Output frequently used variables
  !
  use output_freq_used_vars, only : OutputFreqUsedVars

  !
  ! Calc Mass stream function
  !
  use mass_streamfunc, only :  yr_MassStreamFunc

  ! 宣言文 ; Declaration statements
  !
  implicit none

  character(*), parameter:: prog_name = 'dcpam_main'
                            ! 主プログラム名. 
                            ! Main program name

  ! 予報変数 (ステップ $ t0\Delta t $ )
  ! Prediction variables  (Step $ t-\Delta t $)
  !
  real(DP), allocatable:: xyz_UB (:,:,:)
                              ! $ u (t-\Delta t) $ .   東西風速. Eastward wind (m s-1)
  real(DP), allocatable:: xyz_VB (:,:,:)
                              ! $ v (t-\Delta t) $ .   南北風速. Northward wind (m s-1)
  real(DP), allocatable:: xyz_TempB (:,:,:)
                              ! $ T (t-\Delta t) $ .   温度. Temperature (K)
  real(DP), allocatable:: xyzf_QMixB(:,:,:,:)
                              ! $ q (t-\Delta t) $ .   混合比. Mass mixing ratio of constituents (1)
  real(DP), allocatable:: xy_PsB (:,:)
                              ! $ p_s (t-\Delta t) $ . 地表面気圧. Surface pressure (Pa)

  ! 予報変数 (ステップ $  $ t $ )
  ! Prediction variables  (Step $ t $)
  !
  real(DP), allocatable:: xyz_UN (:,:,:)
                              ! $ u (t) $ .     東西風速. Eastward wind (m s-1)
  real(DP), allocatable:: xyz_VN (:,:,:)
                              ! $ v (t) $ .     南北風速. Northward wind (m s-1)
  real(DP), allocatable:: xyz_TempN (:,:,:)
                              ! $ T (t) $ .     温度. Temperature (K)
  real(DP), allocatable:: xyzf_QMixN(:,:,:,:)
                              ! $ q (t) $ .     混合比. Mass mixing ratio of constituents (1)
  real(DP), allocatable:: xy_PsN (:,:)
                              ! $ p_s (t) $ .   地表面気圧. Surface pressure (Pa)

  ! 予報変数 (ステップ $ t+\Delta t $ )
  ! Prediction variables  (Step $ t+\Delta t $ )
  !
  real(DP), allocatable:: xyz_UA (:,:,:)
                              ! $ u (t+\Delta t) $ .   東西風速. Eastward wind (m s-1)
  real(DP), allocatable:: xyz_VA (:,:,:)
                              ! $ v (t+\Delta t) $ .   南北風速. Northward wind (m s-1)
  real(DP), allocatable:: xyz_TempA (:,:,:)
                              ! $ T (t+\Delta t) $ .   温度. Temperature (K)
  real(DP), allocatable:: xyzf_QMixA(:,:,:,:)
                              ! $ q (t+\Delta t) $ .   混合比. Mass mixing ratio of constituents (1)
  real(DP), allocatable:: xy_PsA (:,:)
                              ! $ p_s (t+\Delta t) $ . 地表面気圧. Surface pressure (Pa)


  ! 診断変数, 他
  ! Diagnostic variables, etc.
  !
  real(DP), allocatable:: xyz_DUDt (:,:,:)
                              ! $ \DP{u}{t} $ . 東西風速変化 (m s-2)
                              ! Eastward wind tendency (m s-2)
  real(DP), allocatable:: xyz_DVDt (:,:,:)
                              ! $ \DP{v}{t} $ . 南北風速変化 (m s-2)
                              ! Northward wind tendency (m s-2)
  real(DP), allocatable:: xyz_DTempDt (:,:,:)
                              ! $ \DP{T}{t} $ . 温度変化 (K s-1)
                              ! Temperature tendency (K s-1)
  real(DP), allocatable:: xyzf_DQMixDt(:,:,:,:)
                              ! $ \DP{q}{t} $ . 混合比変化 (s-1)
                              ! Mass mixing ratio tendency (s-1)
  real(DP), allocatable:: xy_DPsDt (:,:)
                              !  (Pa s-1)
                              ! Surface pressure tendency (Pa s-1)
  real(DP), allocatable:: xy_SurfHeight (:,:)
                              ! $ z_s $ . 地表面高度 (m)
                              ! Surface height (m)
  real(DP), allocatable:: xyz_OMG (:,:,:)
                              ! Vertical velocity in pressure coordinate
  real(DP), allocatable:: yr_Msf (:,:)
                              ! Mass stream function (kg s-1)



  ! スイッチ変数
  ! Variables for switching
  !
  logical:: firstloop = .true.
                              ! 初回のループであることを示すフラグ. 
                              ! Flag implying first loop

  logical:: flag_initial
                              ! 内部サブルーチン MainInit で設定されます. 
                              ! リスタートデータを読み込む場合には, 
                              ! .false. が, 初期値データを読み込む場合には
                              ! .true. が設定されます. 
                              ! 
                              ! This variable is set in an internal 
                              ! subroutine "MainInit". 
                              ! If restart data is loaded, .false. is set. 
                              ! On the other hand, if initial data is loaded, 
                              ! .true. is set.

  integer:: n                 ! 組成方向に回る DO ループ用作業変数
                              ! Work variables for DO loop in dimension of constituents


  ! 実行文 ; Executable statement
  !

  ! 主プログラムの初期化 (内部サブルーチン)
  ! Initialization for the main program (Internal subroutine)
  !
  call MainInit

  ! 時間積分
  ! Time integration
  !
  loop_time : do while ( TimeB < EndTime )

    ! 地表面高度の設定
    ! Set surface height
    !
    xy_SurfHeight = 0.0D0

    ! Held and Suarez (1994) による強制と散逸
    ! Forcing and dissipation suggested by Held and Suarez (1994)
    !
    call HS94Forcing( &
         & xyz_UB, xyz_VB, xyz_TempB, xy_PsB, & ! (in)
         & xyz_DUDt, xyz_DVDt, xyz_DTempDt )    ! (out)
    xy_DPsDt     = 0.0_DP
    xyzf_DQMixDt = 0.0_DP

    ! 力学過程
    ! Dynamical core
    !
    call DynamicsHSplVAS83( &
         & xyz_UB,   xyz_VB,   xyz_TempB,   xyzf_QMixB,   xy_PsB, & ! (in)
         & xyz_UN,   xyz_VN,   xyz_TempN,   xyzf_QMixN,   xy_PsN, & ! (in)
         & xyz_DUDt, xyz_DVDt, xyz_DTempDt, xyzf_DQMixDt,         & ! (in)
         & xy_SurfHeight,                                         & ! (in)
         & xyz_UA,   xyz_VA,   xyz_TempA,   xyzf_QMixA,   xy_PsA, & ! (out)
         & xyz_ArgOMG = xyz_OMG                                   & ! (out) optional
         & )

    ! 時間フィルター (Williams, 2009)
    ! Time filter (Williams, 2009)
    !
    if ( .not. flag_initial .or. .not. firstloop ) then
      call TimeFilterWilliams2009(                 &
        & xyz_UB, xyz_VB, xyz_TempB, xyzf_QMixB, xy_PsB, &   ! (in)
        & xyz_UN, xyz_VN, xyz_TempN, xyzf_QMixN, xy_PsN, &   ! (inout)
        & xyz_UA, xyz_VA, xyz_TempA, xyzf_QMixA, xy_PsA  &   ! (inout)
        & )
    end if


    ! 予報変数の値の確認
    ! Check values of prognostic variables
    !
    call CheckProgVars( &
      & xy_PsA, xyz_UA, xyz_VA, xyz_TempA, xyzf_QMixA   & ! (in)
      & )

    ! ヒストリデータ出力
    ! History data output
    !
    call HistoryAutoPut( TimeA, 'U',    xyz_UA )
    call HistoryAutoPut( TimeA, 'V',    xyz_VA )
    call HistoryAutoPut( TimeA, 'Temp', xyz_TempA )
    do n = 1, ncmax
      call HistoryAutoPut( TimeA, a_QMixName(n), xyzf_QMixA(:,:,:,n) )
    end do
    ! Backward compatibility
    n = IndexH2OVap
    if ( a_QMixName(n) /= 'QVap' ) then
      call HistoryAutoPut( TimeA, 'QVap', xyzf_QMixA(:,:,:,n) )
    end if
    call HistoryAutoPut( TimeA, 'Ps',   xy_PsA )

    yr_MSF = yr_MassStreamFunc( xy_PsA, xyz_VA ) 
    call HistoryAutoPut( TimeA, 'Msf', yr_MSF )

    ! Output frequently used variables
    ! Output frequently used variables
    !
    call OutputFreqUsedVars(           &
      & xy_PsA, xyz_TempA, xyzf_QMixA, & ! (in)
      & xy_SurfHeight                  & ! (in)
      & )

    ! 次の時間ステップに向けて予報変数の入れ替え
    ! Exchange prediction variables for the next time step
    !
    xyz_UB     = xyz_UN     ; xyz_UN     = xyz_UA     ; xyz_UA     = 0.
    xyz_VB     = xyz_VN     ; xyz_VN     = xyz_VA     ; xyz_VA     = 0.
    xyz_TempB  = xyz_TempN  ; xyz_TempN  = xyz_TempA  ; xyz_TempA  = 0.
    xyzf_QMixB = xyzf_QMixN ; xyzf_QMixN = xyzf_QMixA ; xyzf_QMixA = 0.
    xy_PsB     = xy_PsN     ; xy_PsN     = xy_PsA     ; xy_PsA     = 0.


    ! 時刻の進行
    ! Progress time
    !
    call TimesetProgress

    ! NAMELIST から読み込んだ変数名に無効なものが存在したかどうかをチェック
    ! HistoryAutoAddVariable で登録した変数名を印字
    !
    ! Check that invalid variable names are loaded from NAMELIST or not
    ! Print registered variable names by "HistoryAutoAddVariable"
    !
    if ( firstloop ) call HistoryAutoAllVarFix

    ! リスタートデータ出力
    ! Restart data output
    !
    call RestartFileOutput(                            &
      & xyz_UB, xyz_VB, xyz_TempB, xyzf_QMixB, xy_PsB, &  ! (in)
      & xyz_UN, xyz_VN, xyz_TempN, xyzf_QMixN, xy_PsN  &  ! (in)
      & )

    firstloop = .false.

  ! 時間積分終了
  ! Time integration is finished
  !
  end do loop_time

  ! 主プログラムの終了処理 (内部サブルーチン)
  ! Termination for the main program (Internal subroutine)
  !
  call MainTerminate



contains

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

  subroutine MainInit
    !
    ! 主プログラムの初期化手続き. 
    !
    ! Initialization procedure for the main program. 
    !

    ! MPI
    !
    use mpi_wrapper, only : MPIWrapperInit

    !
    ! MPI 計算での Message 制御
    ! Message control for MPI calculation
    !
    use mpi_messagecntl, only : MPIMessageCntlInit

    use dc_message, only: MessageNotify

    ! コマンドライン引数処理
    ! Command line option parser
    !
    use option_parser, only: OptParseInit

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

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

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

    ! 格子点設定
    ! Grid points settings
    !
    use gridset, only: GridsetInit, &
      &                  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

    ! 組成に関わる配列の設定
    ! Settings of array for atmospheric composition
    !
    use composition, only: CompositionInit

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

    ! 雪と海氷の定数の設定
    ! Setting constants of snow and sea ice
    !
    use constants_snowseaice, only: ConstantsSnowSeaIceInit

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

    ! リスタートデータ入出力
    ! Restart data input/output
    !
    use restart_file_io, only: RestartFileInit, RestartFileOpen, RestartFileGet

    ! 地表面温度リスタートデータ入出力
    ! Restart data of surface temperature input/output
    !
    use restart_surftemp_io, only: RestartSurfTempInit, RestartSurfTempOpen, RestartSurfTempGet

    ! ヒストリデータ出力
    ! History data output
    !
    use history_file_io, only: HistoryFileOpen
    use gtool_historyauto, only: &
      & HistoryAutoAddVariable, HistoryAutoAddAttr, HistoryAutoPut

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

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

    ! 時系列データの読み込み
    ! Reading time series
    !
    use read_time_series, only : ReadTimeSeriesInit

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

    ! Held and Suarez (1994) による強制と散逸
    ! Forcing and dissipation suggested by Held and Suarez (1994)
    !
    use held_suarez_1994, only : HS94Init

    ! 力学過程 (スペクトル法, Arakawa and Suarez (1983))
    ! Dynamical process (Spectral method, Arakawa and Suarez (1983))
    !
    use dynamics_hspl_vas83, only : DynamicsHSplVAS83Init

    ! 乾燥対流調節
    ! Dry convective adjustment
    !
    use dry_conv_adjust, only : DryConvAdjustInit

    ! タイムフィルター (Asselin, 1972)
    ! Time filter (Asselin, 1972)
    !
    use timefilter_asselin1972, only : TimeFiltInit

    ! 時間フィルター (Williams, 2009)
    ! Time filter (Williams, 2009)
    !
    use timefilter_williams2009, only: TimeFilterWilliams2009Init

    ! 予報変数の値の確認
    ! Check values of prognostic variables
    !
    use check_prog_vars, only : CheckProgVarsInit

    ! 質量の補正
    ! Mass fixer
    !
    use mass_fixer, only : MassFixerInit

    ! Output frequently used variables
    ! Output frequently used variables
    !
    use output_freq_used_vars, only : OutputFreqUsedVarsInit

    !
    ! Calc Mass stream function
    !
    use mass_streamfunc, only :  yr_MassStreamFunc

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

    ! 宣言文 ; Declaration statements
    !
    implicit none

    character(*), parameter:: version = &
      & '$Name:  $' // &
      & '$Id: dcpam_main_hs94.f90,v 1.67 2025/09/18 11:00:00 takepiro Exp $'
                              ! 主プログラムのバージョン
                              ! Main program version

    character(STRING)      :: namelist_filename
                              ! NAMELIST ファイルの名称. 
                              ! NAMELIST file name


    character(STRING):: CondMajCompName
                                ! name of condensable major component

    character(STRING):: briefexpldyn
                              ! 実行ファイルの簡潔な説明 (力学過程)
                              ! Brief account of executable file (dynamics)
    character(STRING):: briefexplphy
                              ! 実行ファイルの簡潔な説明 (物理過程)
                              ! Brief account of executable file (physics)
    character(STRING):: briefexplrad
                              ! 実行ファイルの簡潔な説明 (放射過程)
                              ! Brief account of executable file (radiation)
    character(STRING):: briefexplsfcflux
                              ! 実行ファイルの簡潔な説明 (惑星表面フラックス)
                              ! Brief account of executable file (surface flux)
    character(STRING):: briefexplvdiff
                              ! 実行ファイルの簡潔な説明 (鉛直拡散過程)
                              ! Brief account of executable file (vertical diffusion)

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

    integer:: n               ! 組成方向に回る DO ループ用作業変数
                              ! Work variables for DO loop in dimension of constituents

!!$    ! NAMELIST 変数群
!!$    ! NAMELIST group name
!!$    !
!!$    namelist /dcpam_main_nml/                                                 &
!!$      & DynMode, PhysMode, RadModel, SfcFluxMethod, VDiffMethod, PhysImpMode, &
!!$      & MCMethod, LSCMethod, CloudMethod, SfcMoistMethod, GWDMethod, DCMethod,&
!!$      & FlagSnow, FlagMajCompPhaseChange, CondMajCompName
!!$          !
!!$          ! デフォルト値については初期化手続 "main/dcpam_main.F90#MainInit" 
!!$          ! のソースコードを参照のこと. 
!!$          !
!!$          ! Refer to source codes in the initialization procedure
!!$          ! "main/dcpam_main.F90#MainInit" for the default values. 
!!$          !

    ! 実行文 ; Executable statement
    !

    ! Initialize MPI
    !
    call MPIWrapperInit

    ! コマンドライン引数処理
    ! Command line option parser
    !
    call OptParseInit(       &
      & namelist_filename,    & ! (out)
      & prog_name            & ! (in )
      & )

    ! NAMELIST ファイル名入力
    ! Input NAMELIST file name
    !
    call NmlutilInit( &
      & namelist_filename  & ! (in)
      & )

    !
    ! MPI 計算での Message 制御
    ! Message control for MPI calculation
    !
    call MPIMEssageCntlInit

!!$    ! 計算モードの設定
!!$    ! Configure calculation mode
!!$    !
!!$    if ( trim(namelist_filename) /= '' ) then
!!$      call FileOpen( unit_nml, &          ! (out)
!!$        & namelist_filename, mode = 'r' ) ! (in)
!!$
!!$      rewind( unit_nml )
!!$      read( unit_nml, &            ! (in)
!!$        & nml = dcpam_main_nml, &  ! (out)
!!$        & iostat = iostat_nml )    ! (out)
!!$      close( unit_nml )
!!$
!!$      call NmlutilMsg( iostat_nml, prog_name ) ! (in)
!!$      if ( iostat_nml == 0 .AND. DoesOutputMPIMessage() ) write( STDOUT, nml = dcpam_main_nml )
!!$    end if


!!$    ! Identification of calculation method for dynamics
!!$    !
!!$    call MessageNotify( 'M', prog_name, &
!!$      & 'DynMode=<%c>.', &
!!$      & c1 = trim(DynMode) )
!!$    !
!!$    select case ( DynMode )
!!$    case ( 'HSPLVAS83' )
!!$      IDDynMode = IDDynModeHSPLVAS83
!!$    case ( 'NoHorAdv' )
!!$      IDDynMode = IDDynModeNoHorAdv
!!$    case ( 'TWPICE' )
!!$      IDDynMode = IDDynModeTWPICE
!!$    case default
!!$      call MessageNotify( 'E', prog_name, &
!!$        & 'DynMode=<%c> is not supported.', &
!!$        & c1 = trim(DynMode) )
!!$    end select
!!$
!!$
!!$    ! Identification of calculation method for physics
!!$    !
!!$    call MessageNotify( 'M', prog_name, &
!!$      & 'PhysMode=<%c>.', &
!!$      & c1 = trim(PhysMode) )
!!$    !
!!$    select case ( PhysMode )
!!$    case ( 'FullPhysics' )
!!$      IDPhysMode = IDPhysModeFullPhysics
!!$    case ( 'HS94' )
!!$      IDPhysMode = IDPhysModeHS94
!!$    case ( 'VenusSimple' )
!!$      IDPhysMode = IDPhysModeVenusSimple
!!$    case ( 'JupiterSimple' )
!!$      IDPhysMode = IDPhysModeJupiterSimple
!!$    case ( 'JupiterSimpleV2' )
!!$      IDPhysMode = IDPhysModeJupiterSimpleV2
!!$    case ( 'NoPhysics' )
!!$      IDPhysMode = IDPhysModeNoPhysics
!!$    case default
!!$      call MessageNotify( 'E', prog_name, &
!!$        & 'PhysMode=<%c> is not supported.', &
!!$        & c1 = trim(PhysMode) )
!!$    end select
!!$
!!$
!!$    ! Identification of calculation method for radiation
!!$    !
!!$    call MessageNotify( 'M', prog_name, &
!!$      & 'RadModel=<%c>.', &
!!$      & c1 = trim(RadModel) )
!!$    !
!!$    select case ( RadModel )
!!$    case ( 'DennouAGCM' )
!!$      IDRadMethod = IDRadMethodDennouAGCM
!!$    case ( 'Earth' )
!!$      IDRadMethod = IDRadMethodEarthV2
!!$    case ( 'Mars' )
!!$      IDRadMethod = IDRadMethodMarsV1
!!$    case ( 'SL09' )
!!$      IDRadMethod = IDRadMethodSL09
!!$    case ( 'VenusSimple' )
!!$      IDRadMethod = IDRadMethodVenusSimple
!!$    case ( 'Simple' )
!!$      IDRadMethod = IDRadMethodSimple
!!$    case ( 'RRTMG' )
!!$      IDRadMethod = IDRadMethodRRTMG
!!$    case ( 'none' )
!!$      IDRadMethod = IDRadMethodNone
!!$    case default
!!$      call MessageNotify( 'E', prog_name, &
!!$        & 'RadModel=<%c> is not supported.', &
!!$        & c1 = trim(RadModel) )
!!$    end select
!!$
!!$    ! Identification of calculation method for surface flux
!!$    !
!!$    call MessageNotify( 'M', prog_name, &
!!$      & 'SfcFluxMethod=<%c>.', &
!!$      & c1 = trim(SfcFluxMethod) )
!!$    !
!!$    select case ( SfcFluxMethod )
!!$    case ( 'L82' )
!!$      IDSfcFluxMethod = IDSfcFluxMethodL82
!!$    case ( 'BH91B94' )
!!$      IDSfcFluxMethod = IDSfcFluxMethodBH91B94
!!$    case default
!!$      call MessageNotify( 'E', prog_name, &
!!$        & 'SfcFluxMethod=<%c> is not supported.', &
!!$        & c1 = trim(SfcFluxMethod) )
!!$    end select
!!$
!!$    ! Identification of calculation method for vertical diffusion
!!$    !
!!$    call MessageNotify( 'M', prog_name, &
!!$      & 'VDiffMethod=<%c>.', &
!!$      & c1 = trim(VDiffMethod) )
!!$    !
!!$    select case ( VDiffMethod )
!!$    case ( 'MY2' )
!!$      IDVDiffMethod = IDVDiffMethodMY2
!!$    case ( 'MY2.5' )
!!$      IDVDiffMethod = IDVDiffMethodMY25
!!$    case ( 'JMA' )
!!$      IDVDiffMethod = IDVDiffMethodJMA
!!$    case default
!!$      call MessageNotify( 'E', prog_name, &
!!$        & 'VDiffMethod=<%c> is not supported.', &
!!$        & c1 = trim(VDiffMethod) )
!!$    end select
!!$
!!$    ! Identification of calculation method for solving simultaneous linear equations 
!!$    ! of physics
!!$    !
!!$    call MessageNotify( 'M', prog_name, &
!!$      & 'PhysImpMode=<%c>.', &
!!$      & c1 = trim(PhysImpMode) )
!!$    !
!!$    select case ( PhysImpMode )
!!$    case ( '1LayModel' )
!!$      IDPhyTendMethod = IDPhyTendMethodImp1LayModel
!!$      FlagPhysImpSoilModelSO = .false.
!!$    case ( 'SoilModel' )
!!$      IDPhyTendMethod = IDPhyTendMethodImpSoilModel
!!$      FlagPhysImpSoilModelSO = .false.
!!$    case ( 'SoilModelSO' )
!!$      IDPhyTendMethod = IDPhyTendMethodImpSoilModel
!!$      FlagPhysImpSoilModelSO = .true.
!!$    case ( 'AtmOnly' )
!!$      IDPhyTendMethod = IDPhyTendMethodImpAtmOnly
!!$      FlagPhysImpSoilModelSO = .false.
!!$    case default
!!$      call MessageNotify( 'E', prog_name, &
!!$        & 'PhysImpMode=<%c> is not supported.', &
!!$        & c1 = trim(PhysImpMode) )
!!$    end select
!!$    !
!!$    !   Check for value of FlagFullPhysics
!!$    !
!!$    if ( ( IDPhysMode /= IDPhysModeFullPhysics ) .and. &
!!$      &  ( IDPhyTendMethod == IDPhyTendMethodImpSoilModel ) ) then
!!$      call MessageNotify( 'E', prog_name, &
!!$        & 'PhysMode has to be "FullPhysics" true, when PhyImpMode is "SoilModel" or "SoilModelSO".' )
!!$    end if
!!$    if ( ( IDPhysMode /= IDPhysModeFullPhysics ) .and. &
!!$      &  ( IDPhyTendMethod == IDPhyTendMethodImpAtmOnly ) ) then
!!$      call MessageNotify( 'E', prog_name, &
!!$        & 'PhysMode has to be "FullPhysics" true, when PhyImpMode is "AtmOnly".' )
!!$    end if
!!$
!!$
!!$    ! Identification of calculation method for moist convection
!!$    !
!!$    call MessageNotify( 'M', prog_name, 'MCMethod=<%c>.', c1 = trim(MCMethod) )
!!$    !
!!$    select case ( MCMethod )
!!$    case ( 'None' )
!!$      IDMCMethod = IDMCMethodNone
!!$    case ( 'MCA' )
!!$      IDMCMethod = IDMCMethodMCA
!!$    case ( 'RAS' )
!!$      IDMCMethod = IDMCMethodRAS
!!$    case ( 'RASWithIce' )
!!$      IDMCMethod = IDMCMethodRASWithIce
!!$    case default
!!$      call MessageNotify( 'E', prog_name, 'MCMethod=<%c> is not supported.', &
!!$        & c1 = trim(MCMethod) )
!!$    end select
!!$
!!$
!!$    ! Identification of calculation method for large scale condensation
!!$    !
!!$    call MessageNotify( 'M', prog_name, 'LSCMethod=<%c>.', &
!!$      & c1 = trim(LSCMethod) )
!!$    !
!!$    select case ( LSCMethod )
!!$    case ( 'None' )
!!$      IDLSCMethod = IDLSCMethodNone
!!$    case ( 'M65' )
!!$      IDLSCMethod = IDLSCMethodM65
!!$!   case ( 'LL91' )
!!$!      IDLSCMethod = IDLSCMethodLL91
!!$    case ( 'SatAdjM65' )
!!$      IDLSCMethod = IDLSCMethodSatAdjM65
!!$    case ( 'M65WithIce' )
!!$      IDLSCMethod = IDLSCMethodM65WithIce
!!$    case ( 'LL91WithIce' )
!!$      IDLSCMethod = IDLSCMethodLL91WithIce
!!$    case default
!!$      call MessageNotify( 'E', prog_name, 'LSCMethod=<%c> is not supported.', &
!!$        & c1 = trim(LSCMethod) )
!!$    end select
!!$
!!$
!!$    ! Identification of calculation method for cloud
!!$    !
!!$    call MessageNotify( 'M', prog_name, 'CloudMethod=<%c>.', &
!!$      & c1 = trim(CloudMethod) )
!!$    !
!!$    select case ( CloudMethod )
!!$    case ( 'None' )
!!$      IDCloudMethod = IDCloudMethodNone
!!$    case ( 'Simple' )
!!$      IDCloudMethod = IDCloudMethodSimple
!!$    case ( 'SimpleWithIce' )
!!$      IDCloudMethod = IDCloudMethodSimpleWithIce
!!$    case ( 'T1993WithIce' )
!!$      IDCloudMethod = IDCloudMethodT1993WithIce
!!$    case ( 'MarsH2OCloud' )
!!$      IDCloudMethod = IDCloudMethodMarsH2OCloud
!!$    case default
!!$      call MessageNotify( 'E', prog_name, 'LSCloudMethod=<%c> is not supported.', &
!!$        & c1 = trim(CloudMethod) )
!!$    end select
!!$    ! check a non-convective condensation
!!$    if ( IDCloudMethod == IDCloudMethodT1993WithIce ) then
!!$      if ( IDLSCMethod /= IDLSCMethodNone ) then
!!$        call MessageNotify( 'E', prog_name, 'If CloudMethod="T1993WithIce", LscMethod has to be "None".' )
!!$      end if
!!$    end if
!!$
!!$    ! Identification of calculation method for surface moisture
!!$    !
!!$    call MessageNotify( 'M', prog_name, 'SfcMoistMethod=<%c>.', &
!!$      & c1 = trim(SfcMoistMethod) )
!!$    !
!!$    select case ( SfcMoistMethod )
!!$    case ( 'None' )
!!$      IDSfcMoistMethod = IDSfcMoistMethodNone
!!$      FlagBucketModel  = .false.
!!$    case ( 'Bucket' )
!!$      IDSfcMoistMethod = IDSfcMoistMethodBucket
!!$      FlagBucketModel  = .true.
!!$    case default
!!$      call MessageNotify( 'E', prog_name, 'SfcMoistMethod=<%c> is not supported.', &
!!$        & c1 = trim(SfcMoistMethod) )
!!$    end select
!!$



    ! 計算モードの表示
    ! Display calculation mode
    !
    briefexpldyn = 'used'

    briefexplphy = 'forcing for Held and Suarez (1994) dynamical core test'

    briefexplrad = ''

    call MessageNotify( 'M', prog_name, '' )
    call MessageNotify( 'M', prog_name,   '+-------------------------------------' )
    call MessageNotify( 'M', prog_name,   '|  Dynamics: %c', c1 = trim(briefexpldyn) )
    call MessageNotify( 'M', prog_name,   '|  -- version = %c', c1 = trim(version) )
    call MessageNotify( 'M', prog_name,   '+-------------------------------------' )
    call MessageNotify( 'M', prog_name, '' )


    ! Initialization of modules used in this module
    !


    ! 時刻管理
    ! Time control
    !
    call TimesetInit

    ! 出力ファイルの基本情報管理
    ! Management basic information for output files
    ! 
    call FilesetInit

    ! 格子点設定
    ! Grid points settings
    !
    call GridsetInit

    ! 組成に関わる配列の設定
    ! Settings of array for atmospheric composition
    !
    call CompositionInit

    ! 物理定数設定
    ! Physical constants settings
    !
    call ConstantsInit

    ! 雪と海氷の定数の設定
    ! Setting constants of snow and sea ice
    !
    call ConstantsSnowSeaIceInit

    ! 座標データ設定
    ! Axes data settings
    !
    call AxessetInit



    ! 時系列データの読み込み
    ! Reading time series
    !
    call ReadTimeSeriesInit

    ! 地表面データ提供
    ! Prepare surface data
    !
    call SurfDataInit



    ! 予報変数の割付
    ! Allocation of prediction variables
    !
    allocate( xyz_UB    (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyz_VB    (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyz_TempB (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyzf_QMixB(0:imax-1, 1:jmax, 1:kmax, 1:ncmax) )
    allocate( xy_PsB    (0:imax-1, 1:jmax) )

    allocate( xyz_UN    (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyz_VN    (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyz_TempN (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyzf_QMixN(0:imax-1, 1:jmax, 1:kmax, 1:ncmax) )
    allocate( xy_PsN    (0:imax-1, 1:jmax) )

    allocate( xyz_UA    (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyz_VA    (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyz_TempA (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyzf_QMixA(0:imax-1, 1:jmax, 1:kmax, 1:ncmax) )
    allocate( xy_PsA    (0:imax-1, 1:jmax) )


    ! リスタートデータ入力
    ! Restart data input
    !
    call RestartFileInit
    call RestartFileGet( &
      & xyz_UB, xyz_VB, xyz_TempB, xyzf_QMixB, xy_PsB, & ! (out)
      & xyz_UN, xyz_VN, xyz_TempN, xyzf_QMixN, xy_PsN, & ! (out)
      & flag_initial )                                   ! (out) optional

    ! リスタートデータファイルの初期化
    ! Initialization of restart data file
    !
    call RestartFileOpen

    ! ヒストリデータファイルの初期化
    ! Initialization of history data files
    !
    call HistoryFileOpen

    ! ヒストリデータ出力のためのへの変数登録
    ! Register of variables for history data output
    !
    call HistoryAutoAddVariable( 'U' , &         ! (in)
      & (/ 'lon ', 'lat ', 'sig ', 'time' /), &  ! (in)
      & 'eastward wind', 'm s-1' )               ! (in)

    call HistoryAutoAddVariable( 'V' , &         ! (in)
      & (/ 'lon ', 'lat ', 'sig ', 'time' /), &  ! (in)
      & 'northward wind', 'm s-1' )              ! (in)

    call HistoryAutoAddVariable( 'Temp' , &      ! (in)
      & (/ 'lon ', 'lat ', 'sig ', 'time' /), &  ! (in)
      & 'temperature', 'K' )                     ! (in)

    do n = 1, ncmax
      call HistoryAutoAddVariable( a_QMixName(n) , & ! (in)
        & (/ 'lon ', 'lat ', 'sig ', 'time' /),    & ! (in)
        & a_QMixLongName(n), 'kg kg-1' )             ! (in)
    end do
    n = IndexH2OVap
    if ( a_QMixName(n) /= 'QVap' ) then
      call HistoryAutoAddVariable( 'QVap' ,        & ! (in)
        & (/ 'lon ', 'lat ', 'sig ', 'time' /),    & ! (in)
        & a_QMixLongName(n), 'kg kg-1' )             ! (in)
    end if

    call HistoryAutoAddVariable( 'Ps' , &        ! (in)
      & (/ 'lon ', 'lat ', 'time' /), &          ! (in)
      & 'surface pressure', 'Pa' )               ! (in)

    call HistoryAutoAddVariable( 'Msf' , &       ! (in)
      & (/ 'lat ', 'sigm', 'time' /), &          ! (in)
      & 'mass stream function', 'kg s-1' )       ! (in)

    ! ヒストリデータ出力 (スタート時刻)
    ! History data output (Start time)
    !
    call HistoryAutoPut( TimeN, 'U', xyz_UN )
    call HistoryAutoPut( TimeN, 'V', xyz_VN )
    call HistoryAutoPut( TimeN, 'Temp', xyz_TempN )
    do n = 1, ncmax
      call HistoryAutoPut( TimeN, a_QMixName(n), xyzf_QMixN(:,:,:,n) )
    end do
    call HistoryAutoPut( TimeN, 'Ps', xy_PsN )
    ! Backward compatibility
    n = IndexH2OVap
    if ( a_QMixName(n) /= 'QVap' ) then
      call HistoryAutoPut( TimeN, 'QVap', xyzf_QMixN(:,:,:,n) )
    end if

    ! Output frequently used variables
    ! Output frequently used variables
    !
    call OutputFreqUsedVarsInit


    ! 診断変数の割付
    ! Allocation of diagnostic variables
    !
    allocate( xyz_DUDt    (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyz_DVDt    (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyz_DTempDt (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xy_DPsDt    (0:imax-1, 1:jmax) )
    allocate( xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax) )

    allocate( xyz_OMG(0:imax-1, 1:jmax, 1:kmax) )
    allocate( xy_SurfHeight(0:imax-1, 1:jmax) )
    allocate( yr_MSF(1:jmax, 0:kmax) )

    yr_MSF = yr_MassStreamFunc( xy_PsN, xyz_VN ) 
    call HistoryAutoPut( TimeN, 'Msf', yr_MSF )

    call HS94Init

    ! 力学過程
    ! Dynamical core
    !
    call DynamicsHSplVAS83Init

    ! タイムフィルター (Asselin, 1972)
    ! Time filter (Asselin, 1972)
    !
!!$    call TimeFiltInit

    ! 時間フィルター (Williams, 2009)
    ! Time filter (Williams, 2009)
    !
    call TimeFilterWilliams2009Init

    ! 予報変数の値の確認
    ! Check values of prognostic variables
    !
    call CheckProgVarsInit

    !
    ! End of initialization
    !

    ! 初回だけはオイラー法を用いるため, Δt を半分に
    ! Delta t is reduced to half in order to use Euler method at initial step
    !
    if ( flag_initial ) then
      call TimesetDelTimeHalf
    end if

  end subroutine MainInit

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

  subroutine MainTerminate
    !
    ! 主プログラムの終了処理手続き. 
    !
    ! Termination procedure for the main program. 
    !

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

    ! MPI
    !
    use mpi_wrapper, only : MPIWrapperFinalize

    ! 力学過程 (スペクトル法, Arakawa and Suarez (1983))
    ! Dynamical process (Spectral method, Arakawa and Suarez (1983))
    !
    use dynamics_hspl_vas83, only : DynamicsHSplVAS83Finalize

    ! Held and Suarez (1994) による強制と散逸
    ! Forcing and dissipation suggested by Held and Suarez (1994)
    !
    use held_suarez_1994, only: Hs94Finalize

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

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

    ! リスタートデータ入出力
    ! Restart data input/output
    !
    use restart_file_io, only: RestartFileClose

    ! 地表面温度リスタートデータ入出力
    ! Restart data of surface temperature input/output
    !
    use restart_surftemp_io, only: RestartSurfTempClose

    ! ヒストリデータ出力
    ! History data output
    !
    use history_file_io, only: HistoryFileClose

    ! 宣言文 ; Declaration statements
    !
    implicit none

    ! 実行文 ; Executable statement
    !

    ! リスタートデータファイルクローズ
    ! Close restart data file
    !
    call RestartFileClose

    ! ヒストリデータファイルクローズ
    ! Close history data files
    !
    call HistoryFileClose

    ! 予報変数の割付解除
    ! Deallocation of prediction variables
    !
    deallocate( xyz_UB     )
    deallocate( xyz_VB     )
    deallocate( xyz_TempB  )
    deallocate( xyzf_QMixB )
    deallocate( xy_PsB     )

    deallocate( xyz_UN     )
    deallocate( xyz_VN     )
    deallocate( xyz_TempN  )
    deallocate( xyzf_QMixN )
    deallocate( xy_PsN     )

    deallocate( xyz_UA     )
    deallocate( xyz_VA     )
    deallocate( xyz_TempA  )
    deallocate( xyzf_QMixA )
    deallocate( xy_PsA     )

    ! 診断変数の割付解除
    ! Dellocation of diagnostic variables
    !
    deallocate( xyz_DUDt     )
    deallocate( xyz_DVDt     )
    deallocate( xyz_DTempDt  )
    deallocate( xyzf_DQMixDt )

    deallocate( xyz_OMG )
    deallocate( yr_MSF )

    deallocate( xy_SurfHeight )

    ! 各モジュール内の変数の割付解除
    ! Dellocation of variables in modules
    !
    call DynamicsHSplVAS83Finalize

    call Hs94Finalize

    call AxessetFinalize

    ! 時刻管理終了処理
    ! Termination of time control
    !
    call TimesetClose

    ! Finalize MPI
    !
    call MPIWrapperFinalize


  end subroutine MainTerminate

end program dcpam_main_hs94
