!################################################################################
!
!> \mainpage IGModel-SW
!! \~japanese
!! \brief IGModel-SW は, 主に Tomita, etal(2001) をもとにして作成した, 正二十面体格子による全球浅水モデルである.
!! \~english
!! \brief IGModel-SW は, 主に Tomita, etal(2001) をもとにして作成した, 正二十面体格子による全球浅水モデルである.
!! \~
!!
!! <br><br>
!! \b Copyright (C) GFD Dennou Club, 2011-2012. All rights reserved. <br>
!! \b license ?? <br>
!! \author Yuta Kawai
!!
!! \~japanese
!! \section sec1 支配方程式系
!!   - 運動方程式は, 以下のようなベクトル不変形にして用いる. 
!!     \f[
!!        \DP{\Dvect{v}}{t} + ( \zeta + f ) \Dvect{k} \times \Dvect{v}
!!        = - \nabla \left( gh + \dfrac{\Dvect{v} \cdot \Dvect{v}}{2} \right)
!!     \f]
!!     ここで, \f$ h, \Dvect{v}, \zeta, f, g \f$はそれぞれ, 流体の表面高度, 速度ベクトル, 相対渦度, 惑星渦度, 重力加速度である.
!!     また, \f$ \Dvect{k} \f$は地理座標系における鉛直方向の単位ベクトルである.
!!
!!   - 連続の式は, 以下のようなフラックスフォームにして用いる. 
!!     \f[
!!        \DP{h}{t} + \nabla \cdot ( h - h_s ) \Dvect{v} = 0
!!     \f]
!!     ここで, \f$ h_s \f$ は下部地形の高度である.
!!
!! \section sec2 格子系
!!   - 正二十面格子の採用
!!   - バネ力学を用いた正二十面格子の改良
!!
!! \section sec3 数値計算手法
!!   - 空間の離散化
!!     - 支配方程式系に現れる空間微分演算子の離散化には, 有限体積法が用いられている. そのため, 輸送される物理量(質量フラックスなど)の全球積分は保存する. 
!!   - 時間積分スキーム
!!     - 三次の Adams-Bashforth 法(ただし, 最初の 2 ステップは, 4 次の Runge=Kutta 法)を用いる.  
!!
!!
!! \~english
!! \section sec1 Governing Equations
!!   - This model applies the flollowing eauation in vector invariant form as the equation of motion.
!!     \f[
!!        \DP{\Dvect{v}}{t} + ( \zeta + f ) \Dvect{k} \times \Dvect{v}
!!        = - \nabla \left( gh + \dfrac{\Dvect{v} \cdot \Dvect{v}}{2} \right)
!!     \f]
!!     where \f$ h, \Dvect{v}, \zeta, f \textrm{and} g \f$ denote the fluid surface height, velocity vector, relative vorticity, Coriolis parameter and  the gravitational acceleration.
!!     And \f$ \Dvect{k} \f$ is vertical unit vector in the geostrophic coordinate.
!!
!!   - 連続の式は, 以下のようなフラックスフォームにして用いる.
!!     \f[
!!        \DP{h}{t} + \nabla \cdot ( h - h_s ) \Dvect{v} = 0
!!     \f]
!!     ここで, \f$ h_s \f$ は下部地形の高度である.
!!
!! \section sec2 Grid System
!!   - The application of icosahedral grid. 
!!   - バネ力学を用いた正二十面格子の改良
!!
!! \section sec3 Numerical Method
!!   - Spatial discretization
!!     - 支配方程式系に現れる空間微分演算子の離散化には, 有限体積法が用いられている. そのため, 輸送される物理量(質量フラックスなど)の全球積分は保存する.
!!   - Temporal integration
!!     - 三次の Adams-Bashforth 法(ただし, 最初の 2 ステップは, 4 次の Runge=Kutta 法)を用いる.
!!
!!
!!
!!
!###############################################################################

!> \~japanese IGModel-SW のメインプログラム.
!! \~english Main program of IGModel-SW.
!!
!! <br><br>
!! \b Copyright:: (C) GFD Dennou Club, 2011-2012. All rights reserved. <br>
!! \b license:: ?? <br>
!! \author Yuta Kawai
!
program IGModelSW_main  

  ! モジュール引用 ; Use statements
  !
  
  ! * gtool *
  ! *

  ! 種類型パラメータ
  ! Kind type parameter
  !
  use dc_types, only: DP, &    ! 倍精度実数型. Double precision. 
    &                 TOKEN, & !
    &                 STRING

  ! メッセージ出力
  ! Output messgae
  !
  use dc_message, only: MessageNotify

  ! * IGMBaseLib *
  ! *

  ! 正二十面体格子の管理クラス
  ! Manager class of icoshedral grid
  !
  use IcGrid2D_FVM_Manager, only: &
    & IcGrid2D_FVM, &
    & IcGrid2D_FVM_Init

  ! 正二十面体格子座標データのローダー
  !
  !
  use IcGrid_ncGridLoader, only: &
    & load_gridData

  ! 正二十面体格子上の物理場に作用する微分演算を提供
  ! Providing some differential operators acting on the physical field on icosahedral grid
  !
  use Derivate_Field_IcGrid2D_Manager, only: &
    & Derivate_Field_IcGrid2D

  ! * IGModel-SW *
  ! *

  ! 物理場データの管理
  ! Manager of the fields 
  !
  use field_manager, only: &
    & xy_Vel_TL_list, xy_Height_TL_list, &
    & DVelDt_TL_list, DHeightDt_TL_list, &
    & xy_Htopo, &
    & TL_N, TL_Nplus1, &
    & TL_DDT_N, TL_DDT_Nminus1, TL_DDT_Nminus2, &
    & init_field_manager, update_timelevel
  
  ! 初期場の生成
  ! Generation of the initial field. 
  !
  !use initial_field_builder, only: &
  !  & init_initial_field_builder, &
  !  & set_initial_fields

  ! シミュレーションパラメータの管理
  ! Manager of simulation parameter
  !
  use param_manager, only: &
    & read_namelistFile, &
    & gridData_ncFile, &
    & div_level, ic_radius, &
    & DelTime, integration_time, &
    & output_data_ncFile, output_tick, &
    & data_output_flag

  ! 浅水方程式ソルバ
  ! Solve shallow water equations
  !
  use sw_equation_solver, only: &
    & init_sw_equation_solver,  &
    & temporal_integration

  ! 物理場データの NetCDF ファイルへの出力 
  ! Output some physical field data into a NetCDF file
  !
  use output_field_data, only: &
    & init_output_field_data, &
    & finalize_output_field_data, &
    & output_field

  ! テストケース
  ! Test case
  !
  use class_TestCase6, only: &
    & TestCase => TestCase6, &
    & initialize_TestCase, finalize_TestCase, &
    & set_initial_v, set_initial_h, set_initial_hs, &
    & timelevel_updated


  ! 宣言文 ; Declaration statements
  !
  implicit none

  !> \~japanese 正二十面体格子を管理する構造型 IcGrid2D_FVM の変数.
  !! \~english  The variable of derived type IcGrid2D_FVM  which manages icosahedral grid.
  type(IcGrid2D_FVM) :: icgrid

  !> \~japanese シミュレーションパラメータなどを設定しているネームリストファイルの名前.
  !! \~english The name of namelist file for configuring the simulation parameters.
  character(STRING) :: nml_filename = 'config.nml' 
  
  !> \~japanese タイムレベルのステップ数.
  !! \~english The number of time level step.
  integer :: tstep = 0
 
  !> \~japanese 終了タイムステップ数.
  !! \~english The number of end time step.
  integer :: end_tstep

  !> \~japanese NetCDF ファイルへデータ出力操作を行うタイムステップの間隔.
  !! \~english  Time step interval for which data output operation is performed.
  integer :: output_tstep

  !> \~japanese output_tstep の 1 割にあたるタイムステップ数.
  !! \~english
  integer :: ten_percent_tstep

  !> \~japanese テストケースを提供する構造型の変数.
  !! \~english The variable of derived type providing test case.
  type(TestCase) :: test_case


  !********************************************************
  !
  ! 実行文 ; Executable statements
  !
  !********************************************************

  !#
  !# 下準備
  !# Preparation

  ! コマンドライン引数の解析を行う. 
  ! Analize the comand line arguments. 
  call analize_cmdline_arg()

  ! ネームリストファイルを読み込んで, 各シミュレーションパラメータを設定する. 
  ! Read the namelist file and configure each parameter. 
  call read_namelistFile(nml_filename)  ! (in)

  ! シミュレーション終了時間, データ書き出しの時間間隔を, 
  ! 時間のステップ数に換算する. 
  end_tstep = integration_time / DelTime 
  ten_percent_tstep = 0.1d0 * end_tstep
  output_tstep = output_tick / DelTime

  ! 格子生成
  ! Grid generation. 

  ! 正二十面体格子管理クラスのインスタンスを初期化する. 
  ! また, 既存のデータファイルから格子座標データを読み込み, IcGrid2D_FVM クラスのオブジェクトに格子点情報を設定する.
  call IcGrid2D_FVM_Init(  &
    & icgrid, &               ! (inout)
    & div_level, ic_radius &  ! (in)
    & )

  call load_gridData( &
    & gridData_ncFile, &  ! (in)
    & icgrid &            ! (inout)
    & )

  ! 各種モジュールの初期化
  ! Initialize each of the modules. 
  !

  ! field_manager モジュールの初期化
  call init_field_manager(icgrid)       ! (in)

  ! sw_equation_solver モジュールの初期化
  call init_sw_equation_solver(icgrid)  ! (in)

  ! output_field_data モジュールの初期化
  call init_output_field_data( &
    & output_data_ncFile, icgrid, &        ! (in) 
    & integration_time, DelTime, output_tick )  ! (in)

  ! テストケースクラスのオブジェクトの初期化  
  call initialize_TestCase(test_case, icgrid)

! initial_field_builder モジュールの初期化
!  call init_initial_field_builder(icgrid, test_case)

  ! 速度および高度の初期場を設定する. 
  call set_initial_v(test_case, xy_Vel_TL_list(TL_N))
  call set_initial_h(test_case, xy_Height_TL_list(TL_N))
  call set_initial_hs(test_case, xy_Htopo)

!  call set_initial_fields( &
!    & v_tl_list(TL_N), h_tl_list(TL_N), h_s )  ! (inout)

  ! 初期場を netCDF ファイルに書き出す. 
  call output_field( &
    & 0, xy_Vel_TL_list(TL_N), xy_Height_TL_list(TL_N), xy_Htopo )  ! (in) 
  

  !# 時間積分ループ
  !# The loop for temporal integration. 
  !#

  ! Test_Case モジュールに対して, 時間積分タイムレベルの更新を行う.
  call timelevel_Updated( &
    & test_case,                       &  ! (inout)
    & tstep, DelTime,                       &  ! (in)
    & xy_Vel_TL_list(TL_N), xy_Height_TL_list(TL_N) &  ! (inout)
     & )

  ! 時間積分ループの開始 
  ! Starts the loop for temporal integration.

  do tstep=1, end_tstep
    
    ! 時間積分が全体の 10 % 分完了したごとに, 進捗状況を標準出力する. 
    if( .not. ten_percent_tstep == 0 ) then
      if ( mod(tstep, ten_percent_tstep ) == 0 ) then
       
        call MessageNotify( "M", "IGModel-SW", "-------- %d/%d", i=(/ tstep, end_tstep /) )    
      end if
    end if

    ! 浅水方程式系の時間積分 
    ! Performs time integration of shallow water equations. 

    call temporal_integration( &
      &    tstep, DelTime, icgrid )     ! (in)

    ! タイムレベルの更新
    ! Updates the time level. 
    
    ! field_manager モジュールに対して, タイムレベルの更新を行う. 
    ! Updates the time level for field_manager manager. 
    call update_timeLevel()

    ! Test_Case モジュールに対して, タイムレベルの更新を行う. 
    ! Updates the time level for Test_Case manager. 
    call timelevel_Updated( &
      &   test_case,                       &  ! (inout)
      &   tstep, DelTime,                       &  ! (in)
      &   xy_Vel_TL_list(TL_N), xy_Height_TL_list(TL_N) &  ! (inout)
      & )

    ! データ書き出し
    ! Outputs data

    ! タイムレベル更新後のタイムレベル n の物理場データを netCDF ファイルに書き出す. 
    if( data_output_flag .and. mod(tstep, output_tstep) == 0 ) then

      call output_field( &
        &    tstep, xy_Vel_TL_list(TL_N), xy_Height_TL_list(TL_N) &  ! (in)
        & )

    end if

  end do

  !#
  !# 後片付け
  !# Finalization
	
  ! テストケースを提供する構造型の変数の最終化.
  ! Finalizes the variable of derived type providing the test case.
  call finalize_TestCase(test_case)

  ! output_field_data モジュールの最終化. 
  ! Finalizes output_field_data module. 
  call finalize_output_field_data()

contains

!
!> \~japanese
!! \brief コマンドライン引数を解析する.
!!
!! コマンドライン引数を解析し, ネームリストファイルの名前を取得する.
!!
!! \~english
!! \brief Analize the command-line arguments
!!
!! Analize the command-line arguments and get the name of a namelist file. 
!! 
subroutine analize_cmdline_arg()
  ! モジュール引用 ; Use statement 
  !

  ! 文字列型
  ! String
  !
  use dc_string, only: StoA

  ! コマンドライン引数の解析
  ! Analization of command-line arguments
  !
  use dc_args, only: ARGS, &
    & DCArgsOpen, DCArgsClose, DCArgsOption, &
    & DCArgsPutLine, DCArgsDebug, DCArgsHelp, DCArgsStrict 

  ! 作業変数
  ! Work variables
  !

  type(ARGS) :: arg
  logical :: OPT_ncfname
  character(STRING) :: VAL_ncfname

  ! 実行文; Executable statement
  !

  call DCArgsOpen(arg)
  call DCArgsOption(arg, StoA('-C', '--config'), OPT_ncfname, VAL_ncfname, &
    &    help="Specify namelist filename for the simulation parameters.[defalut value is " // trim(nml_filename) // "]." )
  
  call DCArgsDebug(arg)
  call DCArgsHelp(arg)
  call DCArgsStrict(arg)

  if( OPT_ncfname ) then
    nml_filename = VAL_ncfname
  end if

end subroutine analize_cmdline_arg

end program IGModelSW_main
