!= 蠎ｧ讓吶ョ繝ｼ繧ｿ險ｭ螳�
!
!= Axes data settings
!
! Authors::   Yoshiyuki O. Takahashi, Yasuhiro MORIKAWA
! Version::   $Id: axesset.F90,v 1.20 2014/05/07 09:39:21 murashin Exp $
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2008. All rights reserved.
! License::   See COPYRIGHT[link:../../../COPYRIGHT]
!

module axesset
  !
  != 蠎ｧ讓吶ョ繝ｼ繧ｿ險ｭ螳�
  !
  != Axes data settings
  !
  ! <b>Note that Japanese and English are described in parallel.</b>
  !
  ! 蠎ｧ讓吶ョ繝ｼ繧ｿ縺ｮ險ｭ螳壹♀繧医�菫晉ｮ｡繧定｡後＞縺ｾ縺�.
  !
  ! 邱ｯ蠎ｦ $ \varphi $ 縺翫ｈ縺ｳ邨悟ｺｦ $ \lambda $ 縺ｮ譬ｼ蟄千せ縺ｯ,
  ! gridset 繝｢繧ｸ繝･繝ｼ繝ｫ縺ｧ險ｭ螳壹＆繧後ｋ譬ｼ蟄千せ謨ｰ縺九ｉ,
  ! {SPMODEL 繝ｩ繧､繝悶Λ繝ｪ}[http://www.gfd-dennou.org/library/spmodel]
  ! 繧堤畑縺�※豎ｺ螳壹＆繧後∪縺�.
  ! 邱ｯ蠎ｦ縺ｮ譬ｼ蟄千せ縺ｮ菴咲ｽｮ縺ｯ繧ｬ繧ｦ繧ｹ邱ｯ蠎ｦ,
  ! 邨悟ｺｦ縺ｮ譬ｼ蟄千せ縺ｮ菴咲ｽｮ縺ｯ遲蛾俣髫斐↓縺ｨ繧九％縺ｨ縺ｫ縺ｪ繧翫∪縺�.
  !
  ! 驩帷峩ﾏ��譬ｼ蟄千せ縺ｯ, 蜊頑紛謨ｰ繝ｬ繝吶Ν (蜷�ｱ､縺ｮ遶ｯ) 縺ｫ縺､縺�※
  ! NAMELIST#Sigma 縺ｫ謖�ｮ壹＠縺ｾ縺�.
  ! 謨ｴ謨ｰ繝ｬ繝吶Ν (蜷�ｱ､縺ｮ荳ｭ蠢�せ) 縺ｯ, 蜊頑紛謨ｰ繝ｬ繝吶Ν縺ｨ constants
  ! 繝｢繧ｸ繝･繝ｼ繝ｫ縺ｧ險ｭ螳壹＆繧後ｋ荵ｾ辯･螟ｧ豌励�螳壼悸豈皮� $ C_p $ 縺翫ｈ縺ｳ
  ! 荵ｾ辯･螟ｧ豌励�豌嶺ｽ灘ｮ壽焚 $ R $ 繧堤畑縺�※豎ｺ螳壹＠縺ｾ縺�.
  ! 驩帷峩ﾏ��譬ｼ蟄千せ縺ｫ縺､縺�※縺ｯ, sigma_data 繝｢繧ｸ繝･繝ｼ繝ｫ縺ｧ逕ｨ諢上＆繧後※縺�ｋ
  ! 繧ゅ�繧剃ｽｿ逕ｨ縺吶ｋ縺薙→繧ょ庄閭ｽ縺ｧ縺�.
  !
  ! Axes data is set and stored.
  !
  ! Grid points of latitude $ \varphi $ and longitude $ \lambda $ are
  ! determined
  ! with number of grid points configured in "gridset" module
  ! by {SPMODEL Library}[http://www.gfd-dennou.org/library/spmodel/index.htm.en]
  ! Grid points of latitude becomes Gaussian latitude,
  ! and grid points of latitude becomes equally spaced.
  !
  !== Variables List
  !
  ! x_Lon               :: 邨悟ｺｦ蠎ｧ讓�
  ! x_Lon_Weight        :: 邨悟ｺｦ蠎ｧ讓咎㍾縺ｿ
  ! DeltaLon            :: 邨悟ｺｦ譬ｼ蟄千せ髢馴囈
  ! InvDeltaLon         :: 邨悟ｺｦ譬ｼ蟄千せ髢馴囈縺ｮ騾�焚
  ! y_Lat               :: 邱ｯ蠎ｦ蠎ｧ讓�
  ! y_Lat_Weight        :: 邱ｯ蠎ｦ蠎ｧ讓咎㍾縺ｿ
  ! z_Sigma             :: $ \sigma $ 繝ｬ繝吶Ν (謨ｴ謨ｰ)
  ! r_Sigma             :: $ \sigma $ 繝ｬ繝吶Ν (蜊頑紛謨ｰ)
  ! z_DelSigma          :: $ \Delta \sigma $ (謨ｴ謨ｰ)
  ! r_DelSigma          :: $ \Delta \sigma $ (蜊頑紛謨ｰ)
  ! w_Number            :: 繧ｹ繝壹け繝医Ν繝��繧ｿ縺ｮ豺ｻ蟄礼分蜿ｷ
  ! spml_inited         :: SPML 繝ｩ繧､繝悶Λ繝ｪ縺ｮ蛻晄悄險ｭ螳壹ヵ繝ｩ繧ｰ
  ! ------------        :: ------------
  ! x_Lon               :: Longitude
  ! x_Lon_Weight        :: Weight of longitude
  ! DeltaLon            :: Interval of longitude grids
  ! InvDeltaLon         :: Inverse of DeltaLon
  ! y_Lat               :: Latitude
  ! y_Lat_Weight        :: Weight of latitude
  ! z_Sigma             :: Full $ \sigma $ level
  ! r_Sigma             :: Half $ \sigma $ level
  ! z_DelSigma          :: $ \Delta \sigma $ (Full)
  ! r_DelSigma          :: $ \Delta \sigma $ (Half)
  ! w_Number            :: Subscript of spectral data
  ! spml_inited         :: Initialization flag of SPML library
  !
  !== Procedures List
  !
  ! AxessetInit     :: 蠎ｧ讓吶ョ繝ｼ繧ｿ縺ｮ險ｭ螳�
  ! AxessetFinalize :: 邨ゆｺ��逅� (繝｢繧ｸ繝･繝ｼ繝ｫ蜀�Κ縺ｮ螟画焚縺ｮ蜑ｲ繧贋ｻ倥￠隗｣髯､)
  ! ------------    :: ------------
  ! AxessetInit     :: Settings of axes data
  ! AxessetFinalize :: Termination (deallocate variables in this module)
  !

  ! 繝｢繧ｸ繝･繝ｼ繝ｫ蠑慕畑 ; USE statements
  !

  ! 譬ｼ蟄千せ險ｭ螳�
  ! Grid points settings
  !
  use gridset, only: &
    &                nmax       , & ! 譛螟ｧ蜈ｨ豕｢謨ｰ.
                                    ! Maximum truncated wavenumber
    &                lmax       , & ! 繧ｹ繝壹け繝医Ν繝��繧ｿ縺ｮ驟榊�繧ｵ繧､繧ｺ
                                    ! Size of array for spectral data
    &                imax       , & ! 邨悟ｺｦ譬ｼ蟄千せ謨ｰ.
                                    ! Number of grid points in longitude
    &                jmax_global, & ! 邱ｯ蠎ｦ譬ｼ蟄千せ謨ｰ (蜈ｨ逅�).
                                    ! Number of grid points in latitude on whole globe
    &                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.

  ! NAMELIST 繝輔ぃ繧､繝ｫ蜈･蜉帙↓髢｢縺吶ｋ繝ｦ繝ｼ繝�ぅ繝ｪ繝�ぅ
  ! Utilities for NAMELIST file input
  !
  use namelist_util, only: MaxNmlArySize
                              ! NAMELIST 縺九ｉ隱ｭ縺ｿ霎ｼ繧驟榊�縺ｮ譛螟ｧ繧ｵ繧､繧ｺ.
                              ! Maximum size of arrays loaded from NAMELIST

  ! 螳｣險譁� ; Declaration statements
  !
  implicit none
  private

  ! 蜈ｬ髢区焔邯壹″
  ! Public procedure
  !
  public:: AxessetInit, AxessetFinalize

  ! 蜈ｬ髢句､画焚
  ! Public variables
  !
  logical, save, public:: axesset_inited = .false.
                              ! 蛻晄悄險ｭ螳壹ヵ繝ｩ繧ｰ.
                              ! Initialization flag

  real(DP), allocatable, save, public:: x_Lon (:)
                              ! $ \lambda $ [rad.] . 邨悟ｺｦ. Longitude
  real(DP), allocatable, save, public:: x_Lon_Weight (:)
                              ! $ \Delta \lambda $ [rad.] .
                              ! 邨悟ｺｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of longitude
  real(DP), allocatable, save, public:: y_Lat (:)
                              ! $ \varphi $ [rad.] . 邱ｯ蠎ｦ. Latitude
  real(DP), allocatable, save, public:: y_Lat_Weight (:)
                              ! $ \Delta \varphi $ [rad.] .
                              ! 邱ｯ蠎ｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of latitude
  real(DP), allocatable, save, public:: z_Sigma (:)
                              ! $ \sigma $ 繝ｬ繝吶Ν (謨ｴ謨ｰ).
                              ! Full $ \sigma $ level
  real(DP), allocatable, save, public:: r_Sigma (:)
                              ! $ \sigma $ 繝ｬ繝吶Ν (蜊頑紛謨ｰ).
                              ! Half $ \sigma $ level
  real(DP), allocatable, save, public:: z_DelSigma (:)
                              ! $ \Delta \sigma $ (謨ｴ謨ｰ).
                              ! $ \Delta \sigma $ (Full)
  real(DP), allocatable, save, public:: r_DelSigma (:)
                              ! $ \Delta \sigma $ (蜊頑紛謨ｰ).
                              ! $ \Delta \sigma $ (half)
  integer, allocatable, save, public:: w_Number (:)
                              ! 繧ｹ繝壹け繝医Ν繝��繧ｿ縺ｮ豺ｻ蟄礼分蜿ｷ.
                              ! Subscript of spectral data
  real(DP), allocatable, save, public:: z_SSDepth(:)
                              ! 蝨ｰ荳九�譬ｼ蟄千せ縺ｮ豺ｱ縺�
                              ! subsurface grid at midpoint of layer
  real(DP), allocatable, save, public:: r_SSDepth(:)
                              ! 蝨ｰ荳九�螻､縺ｮ蠅�阜髱｢縺ｮ豺ｱ縺�
                              ! subsurface grid on interface of layer
  real(DP), allocatable, save, public:: z_SIDepth(:)
                              ! 豬ｷ豌ｷ縺ｮ譬ｼ蟄千せ縺ｮ豺ｱ縺�
                              ! sea ice grid at midpoint of layer
  real(DP), allocatable, save, public:: r_SIDepth(:)
                              ! 豬ｷ豌ｷ縺ｮ螻､縺ｮ蠅�阜髱｢縺ｮ豺ｱ縺�
                              ! sea ice grid on interface of layer
  real(DP), save, public:: DeltaLon
                              ! 邨悟ｺｦ譬ｼ蟄千せ髢馴囈.
                              ! grid interval in longitude
  real(DP), save, public:: InvDeltaLon
                              ! 邨悟ｺｦ譬ｼ蟄千せ髢馴囈縺ｮ騾�焚.
                              ! Inverse of the grid interval in longitude

  logical, save, public:: spml_inited = .false.
                              ! SPML 繝ｩ繧､繝悶Λ繝ｪ縺ｮ蛻晄悄險ｭ螳壹ヵ繝ｩ繧ｰ.
                              ! Initialization flag of SPML library

  character(STRING), parameter, public :: AxnameX   = 'lon'
                              ! axis name for x
  character(STRING), parameter, public :: AxnameY   = 'lat'
                              ! axis name for y
  character(STRING), parameter, public :: AxnameZ   = 'sig'
                              ! axis name for z
  character(STRING), parameter, public :: AxnameR   = 'sigm'
                              ! axis name for r
  character(STRING), parameter, public :: AxnameSSZ = 'ssz'
                              ! axis name for z (subsurface)
  character(STRING), parameter, public :: AxnameSSR = 'sszi'
                              ! axis name for r (subsurface)
  character(STRING), parameter, public :: AxnameSIZ = 'siz'
                              ! axis name for z (sea ice)
  character(STRING), parameter, public :: AxnameSIR = 'sizi'
                              ! axis name for r (sea ice)
  character(STRING), parameter, public :: AxnameWN  = 'wn'
                              ! axis name for wavenumber
  character(STRING), parameter, public :: AxnameT   = 'time'
                              ! axis name for t

  ! 髱槫�髢句､画焚
  ! Private variables
  !
  real(DP), save:: Sigma (1:MaxNmlArySize)
                              ! $ \sigma $ 繝ｬ繝吶Ν (蜊頑紛謨ｰ).
                              ! Half $ \sigma $ level
  real(DP), save:: Depth(1:MaxNmlArySize)
                              ! 蜈･蜉帷畑驟榊�, 蝨ｰ荳九�驩帷峩螻､蠅�阜
                              ! array for input, layer interface of subsurface
                              ! vertical layer
  real(DP), save:: SIDepth(1:MaxNmlArySize)
                              ! 蜈･蜉帷畑驟榊�, 豬ｷ豌ｷ縺ｮ驩帷峩螻､蠅�阜
                              ! array for input, layer interface of sea ice
                              ! vertical layer

  character(*), parameter:: module_name = 'axesset'
                              ! 繝｢繧ｸ繝･繝ｼ繝ｫ縺ｮ蜷咲ｧｰ.
                              ! Module name
  character(*), parameter:: version = &
    & '$Name:  $' // &
    & '$Id: axesset.F90,v 1.20 2014/05/07 09:39:21 murashin Exp $'
                              ! 繝｢繧ｸ繝･繝ｼ繝ｫ縺ｮ繝舌�繧ｸ繝ｧ繝ｳ
                              ! Module version

contains

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

  subroutine AxessetInit
    !
    ! axesset 繝｢繧ｸ繝･繝ｼ繝ｫ縺ｮ蛻晄悄蛹悶ｒ陦後＞縺ｾ縺�.
    ! NAMELIST#axesset_nml 縺ｮ隱ｭ縺ｿ霎ｼ縺ｿ縺ｯ縺薙�謇狗ｶ壹″縺ｧ陦後ｏ繧後∪縺�.
    !
    ! "axesset" module is initialized.
    ! NAMELIST#axesset_nml is loaded in this procedure.
    !

    ! 繝｢繧ｸ繝･繝ｼ繝ｫ蠑慕畑 ; USE statements
    !

    ! 迚ｩ逅��謨ｰ蟄ｦ螳壽焚險ｭ螳�
    ! Physical and mathematical constants settings
    !
    use constants0, only: PI      ! $ \pi $ .
                                  ! 蜀�捉邇�.  Circular constant

    ! 迚ｩ逅�ｮ壽焚險ｭ螳�
    ! Physical constants settings
    !
    use constants, only: &
      &                  CpDry, & ! $ C_p $ [J kg-1 K-1].
                                  ! 荵ｾ辯･螟ｧ豌励�螳壼悸豈皮�.
                                  ! Specific heat of air at constant pressure
      &                  GasRDry  ! $ R $ [J kg-1 K-1].
                                  ! 荵ｾ辯･螟ｧ豌励�豌嶺ｽ灘ｮ壽焚.
                                  ! Gas constant of air

    ! 譬ｼ蟄千せ謨ｰ繝ｻ譛螟ｧ豕｢謨ｰ險ｭ螳�
    ! Number of grid points and maximum truncated wavenumber settings
    !
    use gridset, only: GridsetCheckNumberOfLatGrid

    ! SPMODEL 繝ｩ繧､繝悶Λ繝ｪ, 逅�擇荳翫�蝠城｡後ｒ逅�擇隱ｿ蜥悟�謨ｰ螟画鋤縺ｫ繧医ｊ隗｣縺�(螟壼ｱ､蟇ｾ蠢�)
    ! SPMODEL library, problems on sphere are solved with spherical harmonics
    ! (multi layer is supported)
    !
#ifdef LIB_MPI
#ifdef SJPACK
    use wa_mpi_module_sjpack, only: wa_mpi_Initial, &
      & spml_x_Lon        => x_Lon, &
                              ! $ \lambda $ [rad.] . 邨悟ｺｦ. Longitude
      & spml_x_Lon_Weight => x_Lon_Weight, &
                              ! $ \Delta \lambda $ [rad.] .
                              ! 邨悟ｺｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of longitude
      & spml_y_Lat        => v_Lat, &
                              ! $ \varphi $ [rad.] . 邱ｯ蠎ｦ. Latitude
      & spml_y_Lat_Weight => v_Lat_Weight, &
                              ! $ \Delta \varphi $ [rad.] .
                              ! 邱ｯ蠎ｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of latitude
      & spml_jc => jc
#else
    use wa_mpi_module, only: wa_mpi_Initial, &
      & spml_x_Lon        => x_Lon, &
                              ! $ \lambda $ [rad.] . 邨悟ｺｦ. Longitude
      & spml_x_Lon_Weight => x_Lon_Weight, &
                              ! $ \Delta \lambda $ [rad.] .
                              ! 邨悟ｺｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of longitude
      & spml_y_Lat        => v_Lat, &
                              ! $ \varphi $ [rad.] . 邱ｯ蠎ｦ. Latitude
      & spml_y_Lat_Weight => v_Lat_Weight, &
                              ! $ \Delta \varphi $ [rad.] .
                              ! 邱ｯ蠎ｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of latitude
      & spml_jc => jc
#endif
#elif AXISYMMETRY
    use wa_zonal_module, only: wa_Initial, &
      & spml_x_Lon        => x_Lon, &
                              ! $ \lambda $ [rad.] . 邨悟ｺｦ. Longitude
      & spml_x_Lon_Weight => x_Lon_Weight, &
                              ! $ \Delta \lambda $ [rad.] .
                              ! 邨悟ｺｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of longitude
      & spml_y_Lat        => y_Lat, &
                              ! $ \varphi $ [rad.] . 邱ｯ蠎ｦ. Latitude
      & spml_y_Lat_Weight => y_Lat_Weight
                              ! $ \Delta \varphi $ [rad.] .
                              ! 邱ｯ蠎ｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of latitude
#elif SJPACK
    use wa_module_sjpack, only: wa_Initial, &
      & spml_x_Lon        => x_Lon, &
                              ! $ \lambda $ [rad.] . 邨悟ｺｦ. Longitude
      & spml_x_Lon_Weight => x_Lon_Weight, &
                              ! $ \Delta \lambda $ [rad.] .
                              ! 邨悟ｺｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of longitude
      & spml_y_Lat        => y_Lat, &
                              ! $ \varphi $ [rad.] . 邱ｯ蠎ｦ. Latitude
      & spml_y_Lat_Weight => y_Lat_Weight
                              ! $ \Delta \varphi $ [rad.] .
                              ! 邱ｯ蠎ｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of latitude
#elif AXISYMMETRY_SJPACK
    use wa_zonal_module_sjpack, only: wa_Initial, &
      & spml_x_Lon        => x_Lon, &
                              ! $ \lambda $ [rad.] . 邨悟ｺｦ. Longitude
      & spml_x_Lon_Weight => x_Lon_Weight, &
                              ! $ \Delta \lambda $ [rad.] .
                              ! 邨悟ｺｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of longitude
      & spml_y_Lat        => y_Lat, &
                              ! $ \varphi $ [rad.] . 邱ｯ蠎ｦ. Latitude
      & spml_y_Lat_Weight => y_Lat_Weight
                              ! $ \Delta \varphi $ [rad.] .
                              ! 邱ｯ蠎ｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of latitude
#else
    use wa_module, only: wa_Initial, &
      & spml_x_Lon        => x_Lon, &
                              ! $ \lambda $ [rad.] . 邨悟ｺｦ. Longitude
      & spml_x_Lon_Weight => x_Lon_Weight, &
                              ! $ \Delta \lambda $ [rad.] .
                              ! 邨悟ｺｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of longitude
      & spml_y_Lat        => y_Lat, &
                              ! $ \varphi $ [rad.] . 邱ｯ蠎ｦ. Latitude
      & spml_y_Lat_Weight => y_Lat_Weight
                              ! $ \Delta \varphi $ [rad.] .
                              ! 邱ｯ蠎ｦ蠎ｧ讓咎㍾縺ｿ.
                              ! Weight of latitude
#endif

    ! 驩帷峩ﾏ�Ξ繝吶Ν繝��繧ｿ貅門ｙ
    ! Prepare vertical sigma level data
    !
    use sigma_data, only: SigmaDataGetHalf

    ! NAMELIST 繝輔ぃ繧､繝ｫ蜈･蜉帙↓髢｢縺吶ｋ繝ｦ繝ｼ繝�ぅ繝ｪ繝�ぅ
    ! Utilities for NAMELIST file input
    !
    use namelist_util, only: namelist_filename, NmlutilMsg, NmlutilAryValid

    ! 繝輔ぃ繧､繝ｫ蜈･蜃ｺ蜉幄｣懷勧
    ! File I/O support
    !
    use dc_iounit, only: FileOpen

    ! 遞ｮ蛻･蝙九ヱ繝ｩ繝｡繧ｿ
    ! Kind type parameter
    !
    use dc_types, only: &
      &                 STDOUT, &  ! 讓呎ｺ門�蜉帙�陬�ｽｮ逡ｪ蜿ｷ. Unit number of standard output
      &                 TOKEN      ! 繧ｭ繝ｼ繝ｯ繝ｼ繝�.   Keywords.

    ! 繝｡繝�そ繝ｼ繧ｸ蜃ｺ蜉�
    ! Message output
    !
    use dc_message, only: MessageNotify

    ! 譁�ｭ怜�謫堺ｽ�
    ! Character handling
    !
    use dc_string, only: CPrintf

    ! OpenMP
    !
    !$ use omp_lib

    ! 螳｣險譁� ; Declaration statements
    !
    implicit none

    ! 菴懈･ｭ螟画焚
    ! Work variables
    !
    logical:: flag_generate_sigma
                              ! 驩帷峩螻､謨ｰ縺ｮ蜀�Κ逕滓�縺ｮ縺溘ａ縺ｮ繝輔Λ繧ｰ
                              ! Flag for generation of sigma levels internally
    integer:: i               ! 繧ｹ繝壹け繝医Ν縺ｮ豺ｻ蟄礼分蜿ｷ縺ｧ蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
                              ! Work variables for DO loop in subscript of spectral data
    integer:: k               ! 驩帷峩譁ｹ蜷代↓蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
                              ! Work variables for DO loop in vertical direction
    real(DP):: Kappa          ! $ \kappa = R / C_p $ .
                              ! 荵ｾ辯･螟ｧ豌励↓縺翫￠繧�, 豌嶺ｽ灘ｮ壽焚縺ｮ螳壼悸豈皮�縺ｫ蟇ｾ縺吶ｋ豈�.
                              ! Ratio of gas constant to specific heat in dry air

    real(DP):: LonInDeg       ! Longitude in unit of degree of a grid point in 1D mode
    real(DP):: LatInDeg       ! Latitude in unit of degree of a grid point in 1D mode

    integer:: unit_nml        ! NAMELIST 繝輔ぃ繧､繝ｫ繧ｪ繝ｼ繝励Φ逕ｨ陬�ｽｮ逡ｪ蜿ｷ.
                              ! Unit number for NAMELIST file open
    integer:: iostat_nml      ! NAMELIST 隱ｭ縺ｿ霎ｼ縺ｿ譎ゅ� IOSTAT.
                              ! IOSTAT of NAMELIST read

    integer:: OMPNumThreads
                              ! OpenMP 縺ｧ縺ｮ譛螟ｧ繧ｹ繝ｬ繝�ラ謨ｰ.
                              ! openmp_threads 縺ｫ 1 繧医ｊ螟ｧ縺阪↑蛟､繧呈欠螳壹☆繧後�
                              ! ISPACK[http://www.gfd-dennou.org/library/ispack/]
                              ! 縺ｮ逅�擇隱ｿ蜥悟�謨ｰ螟画鋤 OpenMP 荳ｦ蛻苓ｨ育ｮ�
                              ! 繝ｫ繝ｼ繝√Φ縺檎畑縺�ｉ繧後ｋ. 荳ｦ蛻苓ｨ育ｮ励ｒ螳溯｡後☆繧九↓縺ｯ,
                              ! 螳溯｡梧凾縺ｫ迺ｰ蠅�､画焚 OMP_NUM_THREADS
                              ! 繧� OMPNumThreads 莉･荳九�謨ｰ蟄励↓險ｭ螳壹☆繧�
                              ! 遲峨�繧ｷ繧ｹ繝�Β縺ｫ蠢懊§縺滓ｺ門ｙ縺悟ｿ�ｦ√→縺ｪ繧�.
                              !
                              ! OMPNumThreads 縺ｫ 1 繧医ｊ螟ｧ縺阪↑蛟､繧�
                              ! 謖�ｮ壹＠縺ｪ縺代ｌ縺ｰ荳ｦ蛻苓ｨ育ｮ励Ν繝ｼ繝√Φ縺ｯ蜻ｼ縺ｰ繧後↑縺�.

    character(TOKEN):: rank_str
                              ! 繝ｩ繝ｳ繧ｯ謨ｰ. Rank number
    integer:: myrank_mpi      ! 邱上�繝ｭ繧ｻ繧ｹ謨ｰ. Number of total processes
    integer:: nprocs_mpi      ! 閾ｪ霄ｫ縺ｮ繝励Ο繧ｻ繧ｹ. Number of my process
    integer:: ra              ! MPI 縺ｮ繝ｩ繝ｳ繧ｯ謨ｰ譁ｹ蜷代↓蝗槭ｋ DO 繝ｫ繝ｼ繝礼畑菴懈･ｭ螟画焚
                              ! Work variables for DO loop in rank number of MPI direction

    ! NAMELIST 螟画焚鄒､
    ! NAMELIST group name
    !
    namelist /axesset_nml/ &
      & Sigma, Depth, SIDepth, flag_generate_sigma, &
      & LonInDeg, LatInDeg
          !
          ! 繝�ヵ繧ｩ繝ｫ繝亥､縺ｫ縺､縺�※縺ｯ蛻晄悄蛹匁焔邯� "axesset#AxessetInit"
          ! 縺ｮ繧ｽ繝ｼ繧ｹ繧ｳ繝ｼ繝峨ｒ蜿ら�縺ｮ縺薙→.
          !
          ! Refer to source codes in the initialization procedure
          ! "axesset#AxessetInit" for the default values.
          !

    ! 螳溯｡梧枚 ; Executable statement
    !

    if ( axesset_inited ) return

    !
    ! Set number of OpenMP threads
    !
    OMPNumThreads = 1
    !$ OMPNumThreads = omp_get_max_threads()

    ! 蜑ｲ繧贋ｻ倥￠
    ! Allocation
    !
    allocate( z_Sigma      (1:kmax)   )
    allocate( r_Sigma      (0:kmax)   )
    allocate( z_DelSigma   (1:kmax)   )
    allocate( r_DelSigma   (0:kmax)   )
    allocate( w_Number     (1:lmax)   )

    allocate( r_SSDepth( 0:kslmax ) )
    allocate( z_SSDepth( 1:kslmax ) )

    allocate( r_SIDepth( 0:ksimax ) )
    allocate( z_SIDepth( 1:ksimax ) )

    ! 繝�ヵ繧ｩ繝ｫ繝亥､縺ｮ險ｭ螳�
    ! Default values settings
    !

    ! Sigma (蜊頑紛謨ｰ繝ｬ繝吶Νﾏ�) 縺ｮ蛻晄悄蛟､ (辟｡蜉ｹ縺ｪ蛟､) 縺ｮ險ｭ螳�
    ! Setting of initial value (invalid value) of "Sigma" (half level sigma)
    !
    Sigma = -999.0d0

    ! 蝨ｰ荳九�螻､縺ｮ蠅�阜髱｢豺ｱ縺輔�蛻晄悄蛟､ (辟｡蜉ｹ縺ｪ蛟､) 縺ｮ險ｭ螳�
    ! Setting of initial value (invalid value) of depth of subsurface layer interface
    !
    Depth = -999.0d0

    ! 豬ｷ豌ｷ縺ｮ螻､縺ｮ蠅�阜髱｢豺ｱ縺輔�蛻晄悄蛟､ (辟｡蜉ｹ縺ｪ蛟､) 縺ｮ險ｭ螳�
    ! Setting of initial value (invalid value) of depth of sea ice layer interface
    !
    SIDepth = -999.0d0

    ! 驩帷峩螻､謨ｰ縺ｮ蜀�Κ逕滓�縺ｮ縺溘ａ縺ｮ繝輔Λ繧ｰ縺ｮ險ｭ螳�
    ! Setting of flag for generation of sigma levels internally
    !
    flag_generate_sigma = .false.

    ! Longitude in unit of degree of a grid point in 1D mode
    !
    LonInDeg = 0.0_DP

    ! Latitude in unit of degree of a grid point in 1D mode
    !
    LatInDeg  = 0.0_DP

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

      call NmlutilMsg( iostat_nml, module_name ) ! (in)
    end if

    ! Sigma (蜊頑紛謨ｰ繝ｬ繝吶Νﾏ�) 縺ｮ閾ｪ蜍戊ｨｭ螳�
    ! Automation setting of "Sigma" (half level sigma)
    !
    if ( all( Sigma == -999.0d0 ) ) then
      if ( flag_generate_sigma ) then
        call SigmaDataGetHalf( Sigma(1:kmax+1) ) ! (out)
      else
        call MessageNotify( 'E', module_name, &
          & '  Sigma levels have to be specified if flag_generate_sigma is not true.' )
      end if
    end if

    ! Sigma (蜊頑紛謨ｰ繝ｬ繝吶Νﾏ�) 繝√ぉ繝�け
    ! Check "Sigma" (half level sigma)
    !
    if ( Sigma(1) /= 1.0_DP ) then
      call MessageNotify( 'E', module_name, '  Sigma(1) is not 1, but is %f', &
        & d = (/ Sigma(1) /) )
    end if
    if ( Sigma(kmax+1) /= 0.0_DP ) then
      call MessageNotify( 'E', module_name, '  Sigma(kmax+1) is not 0, but is %f', &
        & d = (/ Sigma(kmax+1) /) )
    end if
    do k = 1, kmax
      if ( Sigma(k+1) > Sigma(k) ) then
        call MessageNotify( 'M', module_name, '  Sigma(%d) = %f > Sigma(%d) = %f', &
            & i = (/ k+1, k /), d = (/ Sigma(k+1), Sigma(k) /) )
        call MessageNotify( 'E', module_name, '  Value of Sigma has to decrease with index.' )
      end if
    end do

    ! r_Sigma (蜊頑紛謨ｰ繝ｬ繝吶Νﾏ�) 險ｭ螳�
    ! Setting of "r_Sigma" (half level sigma)
    !
    r_Sigma(0:kmax) = Sigma(1:kmax+1)

    ! z_DelSigma (謨ｴ謨ｰ繝ｬ繝吶Ν $ \Delta \sigma $ ) 險ｭ螳�
    ! Setting of "z_DelSigma" (full level $ \Delta \sigma $ )
    !
    do k = 1, kmax
      z_DelSigma(k) = r_Sigma(k-1) - r_Sigma(k)
    enddo

    ! z_Sigma (謨ｴ謨ｰ繝ｬ繝吶Νﾏ�) 險ｭ螳�
    ! Setting of "z_Sigma" (full level sigma)
    !
    Kappa = GasRDry / CpDry
    do k = 1, kmax
      z_Sigma(k) = &
        & ( &
        &   (   r_Sigma(k-1) ** ( 1.0_DP + Kappa ) &
        &     - r_Sigma(k)   ** ( 1.0_DP + Kappa ) &
        &   ) / ( z_DelSigma(k) * ( 1.0_DP + Kappa ) ) &
        & ) ** ( 1.0_DP / Kappa )
    enddo

    ! r_DelSigma (蜊頑紛謨ｰ繝ｬ繝吶Ν $ \Delta \sigma $ ) 險ｭ螳�
    ! Setting of "r_DelSigma" (half level $ \Delta \sigma $ )
    !
    r_DelSigma(0)    = r_Sigma(0)    - z_Sigma(1)
    r_DelSigma(kmax) = z_Sigma(kmax) - r_Sigma(kmax)
    do k = 1, kmax - 1
      r_DelSigma(k) = z_Sigma(k) - z_Sigma(k+1)
    end do

    ! 蝨ｰ荳九�螻､縺ｮ蠅�阜髱｢豺ｱ縺輔�繝√ぉ繝�け
    ! Check depth of subsurface layer interface
    !
    if ( all( Depth == -999.0d0 ) ) then
      Depth(0+1:kslmax+1 ) = 0.0_DP
      call MessageNotify( 'W', module_name, 'Depth is not found in namelist file.' )
    end if
    !
    if ( Depth(0+1) /= 0.0_DP ) then
      call MessageNotify( 'E', module_name, '  Depth(0) is not zero, but is %f', &
        & d = (/ Depth(0+1) /) )
    end if
    if ( kslmax >= 1 ) then
      if ( all( Depth(1+1:kslmax+1) >= 0.0_DP ) ) then
        do k = 0, kslmax
          call MessageNotify( 'M', module_name, '  Depth(%d) = %f', &
            & i = (/ k /), d = (/ Depth(k+1) /) )
        end do
        call MessageNotify( 'E', module_name, '  Depth has to be zero or negative.' )
      end if
    end if
    do k = 0, kslmax-1
      if ( Depth(k+1+1) > Depth(k+1) ) then
        call MessageNotify( 'M', module_name, '  Depth(%d) = %f > Depth(%d) = %f', &
            & i = (/ k+1, k /), d = (/ Depth(k+1+1), Depth(k+1) /) )
        call MessageNotify( 'E', module_name, '  Value of Depth has to decrease with index.' )
      end if
    end do

    r_SSDepth(0:kslmax) = Depth(1:kslmax+1)

    do k = 0, kslmax
      call MessageNotify( 'M', module_name, '  r_SSDepth(%d) = %f', &
        i = (/ k /), d = (/ r_SSDepth(k) /) )
    end do

    ! 蝨ｰ荳九�驩帷峩螻､縺ｮ荳ｭ蠢�せ縺ｮ險ｭ螳�
    ! Set midpoint of subsurface grid
    !
    do k = 1, kslmax
      z_SSDepth( k ) = ( r_SSDepth( k-1 ) + r_SSDepth( k ) ) / 2.0d0
    end do

    ! 豬ｷ豌ｷ縺ｮ螻､縺ｮ蠅�阜髱｢豺ｱ縺輔�繝√ぉ繝�け
    ! Check depth of sea ice layer interface
    !
    if ( all( SIDepth == -999.0d0 ) ) then
      SIDepth(0+1:ksimax+1 ) = 0.0_DP
      call MessageNotify( 'W', module_name, 'SIDepth is not found in namelist file.' )
    end if
    !
    if ( SIDepth(0+1) /= 0.0_DP ) then
      call MessageNotify( 'E', module_name, '  SIDepth(0) is not zero, but is %f', &
        & d = (/ SIDepth(0+1) /) )
    end if
    if ( ksimax >= 1 ) then
      if ( all( SIDepth(1+1:ksimax+1) >= 0.0_DP ) ) then
        do k = 0, ksimax
          call MessageNotify( 'M', module_name, '  SIDepth(%d) = %f', &
            & i = (/ k /), d = (/ SIDepth(k+1) /) )
        end do
        call MessageNotify( 'E', module_name, '  SIDepth has to be zero or negative.' )
      end if
    end if
    do k = 0, ksimax-1
      if ( SIDepth(k+1+1) > SIDepth(k+1) ) then
        call MessageNotify( 'M', module_name, '  SIDepth(%d) = %f > SIDepth(%d) = %f', &
            & i = (/ k+1, k /), d = (/ SIDepth(k+1+1), SIDepth(k+1) /) )
        call MessageNotify( 'E', module_name, '  Value of SIDepth has to decrease with index.' )
      end if
    end do

    r_SIDepth(0:ksimax) = SIDepth(1:ksimax+1)

    do k = 0, ksimax
      call MessageNotify( 'M', module_name, '  r_SIDepth(%d) = %f', &
        i = (/ k /), d = (/ r_SIDepth(k) /) )
    end do

    ! 蝨ｰ荳九�驩帷峩螻､縺ｮ荳ｭ蠢�せ縺ｮ險ｭ螳�
    ! Set midpoint of subsurface grid
    !
    do k = 1, ksimax
      z_SIDepth( k ) = ( r_SIDepth( k-1 ) + r_SIDepth( k ) ) / 2.0d0
    end do

    ! 邱ｯ蠎ｦ邨悟ｺｦ縺ｮ險ｭ螳�
    ! Settings of longitude and latitude
    !
    allocate( x_Lon        (0:imax-1) )
    allocate( x_Lon_Weight (0:imax-1) )
    allocate( y_Lat        (1:jmax)   )
    allocate( y_Lat_Weight (1:jmax)   )

    if ( ( imax == 1 ) .and. ( jmax == 1 ) ) then

      x_Lon          = LonInDeg * PI / 180.0_DP
      x_Lon_Weight   = 1.0_DP
      y_Lat          = LatInDeg * PI / 180.0_DP
      y_Lat_Weight   = 1.0_DP

    else
      if ( .not. spml_inited ) then
#ifdef LIB_MPI
        call wa_mpi_Initial( nmax, imax, jmax_global, kmax, OMPNumThreads ) ! (in)
        ! Check number of latitudinal grid on each process
        call GridsetCheckNumberOfLatGrid( spml_jc )
#else
        call wa_Initial( nmax, imax, jmax_global, kmax, OMPNumThreads ) ! (in)
#endif
        spml_inited = .true.
      end if

      x_Lon          = spml_x_Lon
      x_Lon_Weight   = spml_x_Lon_Weight
      y_Lat          = spml_y_Lat
      y_Lat_Weight   = spml_y_Lat_Weight
    end if

    if ( imax /= 1  ) then
      ! DeltaLon, InvDeltaLon縺ｮ險育ｮ�
      ! Caluculate DeltaLon and InvDeltaLon
      DeltaLon = x_Lon(1) - x_Lon(0)
      InvDeltaLon = 1.0_DP/DeltaLon
    else
      DeltaLon = 0.0_DP
      InvDeltaLon = 0.0_DP ! not used
    endif

    ! 繧ｹ繝壹け繝医Ν繝��繧ｿ縺ｮ豺ｻ蟄礼分蜿ｷ縺ｮ險ｭ螳�
    ! Settings of subscript of spectral data
    !
    do i = 1, size(w_Number)
      w_Number(i) = i
    end do

    ! 繝ｩ繝ｳ繧ｯ縺ｫ髢｢縺吶ｋ諠��ｱ縺ｮ蜿門ｾ�
    ! Get information about rank
    !
    myrank_mpi = -1
    nprocs_mpi = 1
    rank_str = ''

    ! 蜊ｰ蟄� ; Print
    !
    call MessageNotify( 'M', module_name, '----- Initialization Messages -----' )

#ifdef SJPACK
    call MessageNotify( 'M', module_name, 'SJPACK : %c', c1 = 'used.' )
#else
    call MessageNotify( 'M', module_name, 'SJPACK : %c', c1 = 'not used.' )
#endif

    call MessageNotify( 'M', module_name, 'OMPNumThreads = %d', i = (/OMPNumThreads/) )

    do ra = 0, nprocs_mpi - 1

      call MessageNotify( 'M', module_name, 'Axes:%c', c1 = trim(rank_str), rank_mpi = -1 )
      call MessageNotify( 'M', module_name, '  x_Lon(%d:%d) [deg.] = %*f', &
        & i = (/ 0, imax - 1/), &
        & d = format_print(x_Lon / PI * 180.0_DP, imax), &
        & n =(/ imax /), rank_mpi = -1 )
      call MessageNotify( 'M', module_name, '  y_Lat(%d:%d) [deg.] = %*f', &
        & i = (/ 1, jmax/), &
        & d = format_print(y_Lat / PI * 180.0_DP, jmax), &
        & n =(/ jmax /), rank_mpi = -1 )
      call MessageNotify( 'M', module_name, '  z_Sigma(%d:%d) = %*f', &
        & i = (/ 1, kmax /), &
        & d = format_print(z_Sigma, kmax), n =(/ kmax /), rank_mpi = -1 )
      call MessageNotify( 'M', module_name, '  r_Sigma(%d:%d) = %*f', &
        & i = (/ 0, kmax /), &
        & d = format_print(r_Sigma, kmax+1), n =(/ kmax+1 /), rank_mpi = -1 )
      call MessageNotify( 'M', module_name, '  w_Number(%d:%d) = %d .. %d', &
        & i = (/ 1, size(w_Number), 1, size(w_Number) /), rank_mpi = -1 )
  !
      call MessageNotify( 'M', module_name, 'Weight:' )
      call MessageNotify( 'M', module_name, '  x_Lon_Weight(%d:%d) = %*f', &
        & i = (/ 0, imax - 1/), &
        & d = format_print(x_Lon_Weight, imax), n =(/ imax /), rank_mpi = -1 )
      call MessageNotify( 'M', module_name, '  y_Lat_Weight(%d:%d) = %*f', &
        & i = (/ 1, jmax/), &
        & d = format_print(y_Lat_Weight, jmax), n =(/ jmax /), rank_mpi = -1 )
      call MessageNotify( 'M', module_name, '  z_DelSigma(%d:%d) = %*f', &
        & i = (/ 1, kmax /), &
        & d = format_print(z_DelSigma, kmax), n =(/ kmax /), rank_mpi = -1 )
      call MessageNotify( 'M', module_name, '' )
    end do

    call MessageNotify( 'M', module_name, '-- version = %c', c1 = trim(version), rank_mpi = -1 )

    axesset_inited = .true.

  end subroutine AxessetInit

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

  subroutine AxessetFinalize
    !
    ! 繝｢繧ｸ繝･繝ｼ繝ｫ蜀�Κ縺ｮ螟画焚縺ｮ蜑ｲ繧贋ｻ倥￠隗｣髯､繧定｡後＞縺ｾ縺�.
    !
    ! Deallocate variables in this module.
    !

    ! 繝｢繧ｸ繝･繝ｼ繝ｫ蠑慕畑 ; USE statements
    !

    ! 螳｣險譁� ; Declaration statements
    !
    implicit none

    ! 螳溯｡梧枚 ; Executable statement
    !

    if ( .not. axesset_inited ) return

    ! 蜑ｲ繧贋ｻ倥￠隗｣髯､
    ! Deallocation
    !
    if ( allocated( z_Sigma    ) ) deallocate( z_Sigma    )
    if ( allocated( r_Sigma    ) ) deallocate( r_Sigma    )
    if ( allocated( z_DelSigma ) ) deallocate( z_DelSigma )
    if ( allocated( r_DelSigma ) ) deallocate( r_DelSigma )
    if ( allocated( w_Number   ) ) deallocate( w_Number   )

    if ( allocated( r_SSDepth ) ) deallocate( r_SSDepth )
    if ( allocated( z_SSDepth ) ) deallocate( z_SSDepth )

    if ( allocated( r_SIDepth ) ) deallocate( r_SIDepth )
    if ( allocated( z_SIDepth ) ) deallocate( z_SIDepth )

    if ( allocated( x_Lon        ) ) deallocate( x_Lon        )
    if ( allocated( x_Lon_Weight ) ) deallocate( x_Lon_Weight )
    if ( allocated( y_Lat        ) ) deallocate( y_Lat        )
    if ( allocated( y_Lat_Weight ) ) deallocate( y_Lat_Weight )

    axesset_inited = .false.

  end subroutine AxessetFinalize

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

  function format_print( ary, size ) result(result)
    !
    ! 讓呎ｺ門�蜉帙＠縺ｦ隕九ｄ縺吶＞繧医≧縺ｫ驕ｩ蠖薙↓譛牙柑謨ｰ蟄励�譯√ｒ關ｽ縺ｨ縺励※霑斐☆.
    !
    ! Effective digit is reduced for output to standard output and returned.
    !

    ! 螳｣險譁� ; Declaration statements
    !
    implicit none
    integer, intent(in):: size
    real(DP), intent(in):: ary(size)
    real(DP):: result(size)

    ! 螳溯｡梧枚 ; Executable statement
    !
    result(1:size) = int( ary(1:size) * 1000.0_DP ) / 1000.0_DP

  end function format_print

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

end module axesset