!> \~japanese
!! \brief 物理場データの管理オブジェクトに対する基底クラスを提供するモジュール.
!! \~english
!! \brief This module provides the base type for some objects to manage the physical field data.
!! \~
!!
!! <br><br>
!! \b Copyright (C) GFD Dennou Club, 2011-2012. All rights reserved. <br>
!! \b license ?? <br>
!! \author Yuta Kawai
!!
module Physical_Field_Manager

  ! モジュール引用; Use statement
  !

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

  ! 宣言文 ; Declaration statement
  !
  implicit none
  private

  !> \~japanese
  !! \brief 物理場データの管理オブジェクトに対する基底クラス.
  !!
  !! \~english
  !! \brief This type is a Base type for some objects to manage the physical field data.
  !!
  !!
  type, public :: Physical_Field

    !> \~japanese 物理場の短い名前.
    !! \~english The (short) name of a physical field.
    character(TOKEN) :: field_name
    ! f2003: character(TOKEN), private :: field_name

    !> \~japanese 物理場の長い名前(または, field_name の詳細な説明文).
    !! \~english The name of (or explanation for) a physical field.
    character(STRING) :: long_name
    ! f2003: character(STRING), private :: long_name

    !> \~japanese 物理場の単位.
    !! \~english The unit of a physical field.
    character(TOKEN) :: units
    ! f2003: character(TOKEN), private :: units

    !> \~japanese 物理場のランク.
    !! \~english The rank of a physical field.
    integer :: field_rank
    ! f2003: integer, private :: field_rank

  end type Physical_Field

  ! 公開手続き
  ! Public procedures
  !
  public :: Physical_Field_Init, Physical_Field_Final
  public :: get_field_name, get_long_field_name, get_field_rank, get_field_units
  public :: set_field_name, set_long_field_name, set_field_units

contains


!
!> \~japanese
!! \brief 構造型 Physical_Field の変数の初期化を行う.
!!
!! @param[in,out] self       構造型 Physical_Field の変数.
!! @param[in]     name       物理場の(短い)名前.
!! @param[in]     field_rank  物理場のランク.
!! @param[in]     long_name  物理場の長い名前(あるいは物理場の解説文).
!! @param[in]     units      物理場の単位.
!!
!! \~english
!! \brief Initialize a variable of derived type Physical_Field.
!!
!! @param[in,out] self       The variable of derived type Physical_Field.
!! @param[in]     name       The (short) name of the physical field.
!! @param[in]     field_rank  The rank of the physical filed.
!! @param[in]     long_name  The long name of (or the explanation for) the physical field.
!! @param[in]     units      The unit of the physical field.
!!
subroutine Physical_Field_Init(self, name, field_rank, long_name, units)

  ! 宣言文 ; Declaration statement
  !
  type(Physical_Field), intent(inout) :: self
  character(*), intent(in) :: name
  integer, intent(in) :: field_rank
  character(*), intent(in), optional :: long_name
  character(*), intent(in), optional :: units

  ! 実行文 ; Executable statement
  !
  self%field_name = name
  self%field_rank = field_rank


  if ( present(long_name) ) self%long_name = long_name
  if ( present(units) ) self%units = units

end subroutine Physical_Field_Init

!
!> \~japanese
!! \brief 構造型 Physical_Field の変数の最終化を行う.
!!
!! @param[in,out] self       構造型 Physical_Field の変数.
!!
!! \~english
!! \brief Finalizes a variable of derived type Physical_Field.
!!
!! @param[in,out] self       The variable of derived type Physical_Field.
!!
subroutine Physical_Field_Final(self)

  ! 宣言文 ; Declaration statement
  !
  type(Physical_Field), intent(inout) :: self

end subroutine Physical_Field_Final

!
!> \~japanese
!! \brief 物理場の長い名前(あるいは解説文)を取得する.
!!
!! @param[in] self  構造型 Physical_Field の変数.
!! @return     val  物理場の長い名前(あるいは解説文).
!!
!! \~english
!! \brief Get the long name of (or explanation for) the physcial field.
!!
!! @param[in]  self The reference of Physical_Field type object.
!! @return     val  The long name of (or explanation for) the physical field.
!!
function get_long_field_name(self) result(val)

  ! 宣言文 ; Declaration statement
  !
  type(Physical_Field), intent(in) :: self
  character(STRING) val

  ! 実行文 ; Executable statement
  !

  val = self%long_name

end function get_long_field_name

!
!> \~japanese
!! \brief 物理場の長い名前(あるいは解説文)を設定する.
!!
!! @param[in,out] self 構造型 Physical_Field の変数.
!! @param[in] long_name 物理場の長い名前(あるいは解説文).
!!
!! \~english
!! \brief Set the long name of (or explanation for) the physcial field.
!!
!! @param[in,out] self  The variable of derived type Physical_Field.
!! @param[in] long_name The long name of (or explanation for) the physical field.
!!
subroutine set_long_field_name(self, long_name)
  ! 宣言文 ; Declaration statement
  !
  type(Physical_Field), intent(inout) :: self
  character(*), intent(in) ::  long_name

  ! 実行文 ; Executable statement
  !

  self%long_name = long_name

end subroutine set_long_field_name

!
!> \~japanese
!! \brief 物理場の単位を取得する.
!!
!! @param[in] self  構造型 Physical_Field の変数.
!! @reeturn    val 物理場の単位.
!!
!! \~english
!! \brief Get the unit of the physical field.
!!
!! @param[in] self       The variable of derived type Physical_Field.
!! @reeturn    val The unit of the physical field.
!!
function get_field_units(self) result(val)
  ! 宣言文 ; Declaration statement
  !
  type(Physical_Field), intent(in) :: self
  character(TOKEN) val

  ! 実行文 ; Executable statement
  !

  val = self%units

end function get_field_units

!
!> \~japanese
!! \brief 物理場の単位を設定する.
!!
!! @param[in,out] self 構造型 Physical_Field の変数.
!! @param[in] units 物理場の単位.
!!
!! \~english
!! \brief Set the unit of the physical field.
!!
!! @param[in,out] self       The variable of derived type Physical_Field.
!! @param[in] units The unit of the physical field.
!!
subroutine set_field_units(self, units)
  ! 宣言文 ; Declaration statement
  !
  type(Physical_Field), intent(inout) :: self
  character(*), intent(in) ::  units

  ! 実行文 ; Executable statement
  !

  self%units = units

end subroutine set_field_units

!
!> \~japanese
!! \brief 物理場のランクを取得する.
!!
!! @param[in] self  構造型 Physical_Field の変数.
!! @reeturn    val 物理場のランク.
!!
!! \~english
!! \brief Get the rank of the physical field.
!!
!! @param[in] self       The variable of derived type Physical_Field.
!! @return    val The rank of the physical field.
!!
function get_field_rank(self) result(val)
  ! 宣言文 ; Declaration statement
  !
  type(Physical_Field), intent(in) :: self
  integer val

  ! 実行文 ; Executable statement
  !

  val = self%field_rank

end function get_field_rank


!
!> \~japanese
!! \brief 物理場の(短い)名前を取得する.
!!
!! @param[in] self  構造型 Physical_Field の変数.
!! @return 物理場の(短い)名前.
!!
!! \~english
!! \brief Get the (short) name of the physical field.
!!
!! @param[in] self       The variable of derived type Physical_Field.
!! @return The (short) name of the physical field.
!!
function get_field_name( &
  & self &
  & ) result(name)

  ! 宣言文 ; Declaration statement
  !
  type(Physical_Field), intent(in) :: self       !
  character(TOKEN) name

  ! 実行文 ; Executable statement
  !

  name = self%field_name

end function get_field_name

!
!> \~japanese
!! \brief 物理場の(短い)名前を設定する.
!!
!! @param[in,out] self 構造型 Physical_Field の変数.
!! @param[in] name 物理場の(短い)名前.
!!
!! \~english
!! \brief Set the (short) name of the physical field.
!!
!! @param[in,out] self       The variable of derived type Physical_Field.
!! @param[in] name The (short) name of the physical field.
!!
subroutine set_field_name(self, name)
  ! 宣言文 ; Declaration statement
  !
  type(Physical_Field), intent(inout) :: self
  character(*), intent(in) ::  name

  ! 実行文 ; Executable statement
  !

  self%field_name = name


end subroutine set_field_name

end module Physical_Field_Manager

