!= 初期値データファイル生成主プログラム
!
!= dcpam main program for generation of initial data file
!
! Authors::   Yasuhiro MORIKAWA
!             modified by Shin-ichi Takehiro for venus experiments of primitive model.
! Version::   $Id: init_data_primitive_venus.f90,v 1.4 2010-09-10 10:03:22 takepiro Exp $
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2008. All rights reserved.
! License::   See COPYRIGHT[link:../../../COPYRIGHT]
!

program init_data
  !
  ! <b>Note that Japanese and English are described in parallel.</b>
  !
  ! 初期値データファイルを生成します. 
  !
  ! Initial data file is created. 
  !

  ! モジュール引用 ; 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
  ! 座標データ設定
  ! Axes data settings
  !
  use axesset, only: &
    & x_Lon, &
                            ! $ \lambda $ [rad.] . 経度. Longitude
    & y_Lat, &
                            ! $ \varphi $ [rad.] . 緯度. Latitude
    & z_Sigma
                            ! $ \sigma $ レベル (整数). 
                            ! Full $ \sigma $ level

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

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

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

  ! 温度の半整数σレベルの補間, 気圧と高度の算出
  ! Interpolate temperature on half sigma level, 
  ! and calculate pressure and height
  !
  use auxiliary, only: AuxVars

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

  ! 簡単金星計算のための強制
  ! forcing for simple Venus calculation
  !
  use venus_simple_forcing, only: VenusSimpleNCTempEq

  ! 宣言文 ; Declaration statements
  !
  implicit none

  ! 予報変数 (ステップ $ t-\Delta t $ , $ t $ , $ t+\Delta t $ )
  ! Prediction variables  (Step $ t-\Delta t $ , $ t $ , $ t+\Delta t $ )
  !
  real(DP), allocatable:: xyz_U (:,:,:)
                              ! $ u $ .   東西風速. Eastward wind
  real(DP), allocatable:: xyz_V (:,:,:)
                              ! $ v $ .   南北風速. Northward wind
  real(DP), allocatable:: xyz_Temp (:,:,:)
                              ! $ T $ .   温度. Temperature
  real(DP), allocatable:: xy_Ps (:,:)
                              ! $ p_s $ . 地表面気圧. Surface pressure

  real(DP), allocatable:: xyz_TempB (:,:,:)
                              ! $ T (t-\Delta t) $ .   温度. Temperature (K)
  real(DP), allocatable:: xyz_TempN (:,:,:)
                              ! $ T (t) $ .     温度. Temperature (K)

  ! 診断変数, 他
  ! Diagnostic variables, etc.
  !
  real(DP), allocatable:: xy_SurfHeight (:,:)
                              ! $ z_s $ . 地表面高度 (m)
                              ! Surface height (m)
  real(DP), allocatable:: xyz_Height (:,:,:)
                              ! 高度 (整数レベル) (m)
                              ! Height (full level) (m)
  ! 作業変数
  ! Work variables
  !
  integer:: i                 ! 経度方向に回る DO ループ用作業変数
                              ! Work variables for DO loop in longitude
  integer:: j                 ! 緯度方向に回る DO ループ用作業変数
                              ! Work variables for DO loop in latitude
  integer:: k                 ! 鉛直方向に回る DO ループ用作業変数
                              ! Work variables for DO loop in vertical direction
  integer:: n                 ! 組成方向に回る DO ループ用作業変数
                              ! Work variables for DO loop in dimension of constituents

  real(DP):: eps              ! 温度の誤差
  real(DP),parameter:: &
             eps_null=1.0d-10
                              ! 温度の誤差が微小であることの判定基準

  real(DP):: UInit            ! 初期に与える一様速度東西成分
			      ! The initial uniform longitudinal velocity
  real(DP):: TempInit         ! 初期に与える一様温度
			      ! The initial uniform temp. 
  real(DP):: PsInit           ! 初期に与える一様表面気圧
			      ! The initial uniform surface pressure. 
  real(DP):: TempDist_Amp     ! 出力データに与える温度擾乱の振幅
			      ! The amplitude of temp. dist. of the output data


  ! NAMELIST 変数群
  ! NAMELIST group name
  !
  namelist /init_data_venus_nml/ UInit, TempInit, PsInit, TempDist_Amp


  ! 実行文 ; Executable statement
  !

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

  ! 緩和計算
  ! relaxation calculation
  !
  do while ( eps < eps_null )

    ! 温度の半整数σレベルの補間, 気圧と高度の算出
    ! Interpolate temperature on half sigma level,
    ! and calculate pressure and height
    !
    call AuxVars( &
      & xy_Ps,      xyz_TempB,                               & ! (in )
      & xy_SurfHeight = xy_SurfHeight,                       & ! (in ) optional
      & xyz_Height    = xyz_Height                           & ! (out) optional
      & )

    call VenusSimpleNCTempEq( &
         & xyz_Height, &
         & xyz_TempN   &
         & )

    eps = maxval(abs(xyz_TempN - xyz_TempB))

    ! 次の時間ステップに向けて予報変数の入れ替え
    ! Exchange prediction variables for the next time step
    !
    xyz_TempB  = xyz_TempN

  ! 緩和計算終了
  ! Relaxation calculation is finished
  !
  end do
  !
  ! ヒストリデータ出力
  ! History data output
  !
  call HistoryAutoPut( TimeN, 'Temp',   xyz_TempB )
  call HistoryAutoPut( TimeN, 'Height', xyz_Height )

  xyz_Temp = xyz_TempB

  ! 温度に擾乱を与える
  ! Add perturbation to temperature
  !
  do k = 1, kmax
    do j = 1, jmax
      do i = 0, imax - 1
        xyz_Temp(i,j,k) = &
          &    xyz_Temp(i,j,k) &
          &  + TempDist_Amp * sin ( x_Lon(i) * y_Lat(j) ) &
          &  - TempDist_Amp * ( 1.0_DP - z_Sigma(k) )
      end do
    end do
  end do

  ! 初期値データの出力
  ! Output initial data
  !
  call RestartFileOutput( &
    & xyz_U, xyz_V, xyz_Temp, xy_Ps )  ! (in)

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

contains

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

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

    ! MPI
    !
    use mpi_wrapper, only : MPIWrapperInit

    !
    use dc_message, only: MessageNotify

    use dc_types, only: &
      & STDOUT               ! 標準出力の装置番号. Unit number of standard output
    ! ファイル入出力補助
    ! File I/O support
    !
    use dc_iounit, only: FileOpen

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

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

    ! 時刻管理
    ! Time control
    !
    use timeset, only: TimesetInit
                              ! ステップ $ 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

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

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

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

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

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

    ! 宣言文 ; Declaration statements
    !
    implicit none
    character(*), parameter:: prog_name = 'init_data_primitive_venus'
                              ! 主プログラム名. 
                              ! Main program name
    character(*), parameter:: version = &
      & '$Name:  $' // &
      & '$Id: init_data_primitive_venus.f90,v 1.4 2010-09-10 10:03:22 takepiro Exp $'
                              ! 主プログラムのバージョン
                              ! Main program version
    character(STRING):: brief
                              ! 実行ファイルの簡潔な説明
                              ! Brief account of executable file

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

    ! 実行文 ; Executable statement
    !

    ! Initialize MPI
    !
    call MPIWrapperInit

    brief = 'Initial data generation'
    call MessageNotify( 'M', prog_name, 'Run: %c', c1 = trim(brief) )
    call MessageNotify( 'M', prog_name, '-- version = %c', c1 = trim(version) )

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

    ! NAMELIST ファイル名入力
    ! Input NAMELIST file name
    !
    call NmlutilInit

    UInit        = 400.0d0
    TempInit     = 400.0d0
    PsInit       = 9.2d6
    TempDist_Amp = 1.0d-2

    ! NAMELIST init_data_venus_nml
    !
    if ( trim(namelist_filename) /= '' ) then
      call FileOpen( unit_nml, &          ! (out)
        & namelist_filename, mode = 'r' ) ! (in)

      TempDist_Amp = 0.0_DP
      rewind( unit_nml )
      read( unit_nml, &            ! (in)
           & nml = init_data_venus_nml, &  ! (out)
           & iostat = iostat_nml )    ! (out)
      close( unit_nml )

      call NmlutilMsg( iostat_nml, prog_name ) ! (in)
      if ( iostat_nml == 0 ) write( STDOUT, nml = init_data_venus_nml )
    end if

    ! 時刻管理
    ! Time control
    !
    call TimesetInit

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

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

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

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

    ! 予報変数の割付
    ! Allocation of prediction variables
    !
    allocate( xyz_U    (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyz_V    (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xyz_Temp (0:imax-1, 1:jmax, 1:kmax) )
    allocate( xy_Ps    (0:imax-1, 1:jmax) )


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

    ! 診断変数の割付
    ! Allocation of diagnostic variables
    !
    allocate( xy_SurfHeight (0:imax-1, 1:jmax) )
    allocate( xyz_Height (0:imax-1, 1:jmax, 1:kmax) )

    ! 初期値データ出力
    ! Initial data output
    !
    call RestartFileOpen( flag_init_data = .true. ) ! (in) optional

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

    ! ヒストリデータ出力のためのへの変数登録
    ! Register of variables for history data output
    !
    call HistoryAutoAddVariable( 'Temp' , &      ! (in)
      & (/ 'lon ', 'lat ', 'sig ', 'time' /), &  ! (in)
      & 'temperature', 'K' )                     ! (in)
    call HistoryAutoAddVariable( 'Height', &
      & (/ 'lon ', 'lat ', 'sig ', 'time' /), &
      & 'Height', 'm' )

    ! 緩和計算初期値設定
    !
    xy_SurfHeight = 0.0D0
    xyz_TempB = TempInit

    xyz_U     = UInit
    xyz_V     = 0.0d0
    xy_Ps     = PsInit

  end subroutine MainInit

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

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

    ! MPI
    !
    use mpi_wrapper, only : MPIWrapperFinalize

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

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

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

    ! 宣言文 ; Declaration statements
    !
    implicit none

    ! 実行文 ; Executable statement
    !

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

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

    ! 予報変数の割付解除
    ! Deallocation of prediction variables
    !
    deallocate( xyz_U    )
    deallocate( xyz_V    )
    deallocate( xyz_Temp )
    deallocate( xy_Ps    )

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

    ! Finalize MPI
    !
    call MPIWrapperFinalize

  end subroutine MainTerminate

end program init_data
