!> \~japanese
!! \brief
!!
!! \par Field_Grid1D_Manager モジュールについて
!!
!! \~english
!! \brief
!!
!! \par About Field_Grid1D_Manager module
!!
!! \~
!! \since IGMBaseLib 1.1
!!
!! <br><br>
!! \b Copyright (C) GFD Dennou Club, 2011-2012. All rights reserved. <br>
!! \b license ?? <br>
!! \author Yuta Kawai
!!
module Field_Grid1D_Manager

  use dc_types, only: &
    & DP, TOKEN, STRING

  ! 物理場データを管理する構造体のための基底モジュール
  ! Base module for some derived types to manage the physical field data
  !
  use Physical_Field_Manager, only: &
    & Physical_Field, &
    & Physical_Field_Init, Physical_Field_Final, &
    & get_name_ => get_field_name, &
    & get_long_name_ => get_long_field_name, &
    & get_dimension_ => get_field_rank, &
    & get_units_ => get_field_units, &
    & set_name_ => set_field_name, &
    & set_long_name_ => set_long_field_name, &
    & set_units_ => set_field_units

  ! 宣言文 ; Declaration statement
  !
  implicit none
  private

  type, public :: Field_Grid1D
    real(DP), pointer :: val(:,:)
    real(DP), pointer :: grid1D(:)
    type(Physical_Field) ::  base
  end type Field_Grid1D


  ! interface 文 ; interface statements
  !
  interface Field_Grid1D_Init
    module procedure init_Field_Grid1D0
    module procedure init_Field_Grid1D2
  end interface Field_Grid1D_Init

  public :: Field_Grid1D_Init, Field_Grid1D_Final
  public :: get_grid1D, get_Physical_Field

  public :: get_field1D_name, get_long_field1D_name, get_field1D_rank, get_field1D_units
  public :: set_field1D_name, set_long_field1D_name, set_field1D_units

contains

subroutine init_Field_Grid1D0( &
  & self,                     &  ! (inout)
  & grid1D, name, field_rank, &  ! (in)
  & long_name, units          &  ! (in)
  & )

  ! 宣言文 ; Declaration statement
  !
  type(Field_Grid1D), intent(inout) :: self
  real(DP), intent(in), target :: grid1D(:)
  character(*), intent(in) :: name
  integer, intent(in) :: field_rank
  character(*), intent(in) :: long_name
  character(*), intent(in) :: units

  ! 作業変数
  ! Work variables
  !
  integer :: idMin, idMax

  ! 実行文 ; Executable statement
  !
!  write(*,*) 'Field_Grid1D initialize, name=', trim(name)

  self%grid1D => grid1D

  ! 物理場データを格納する配列のメモリを確保する.
  allocate(self%val(size(grid1D), 1:field_rank))

  ! 基底構造体の初期化関数を呼び出す.
  call Physical_Field_Init(self%base, name, field_rank, long_name, units)

end subroutine init_Field_Grid1D0

subroutine init_Field_Grid1D2( &
  & self,              &  ! (inout)
  & grid1D, name, rank &  ! (in)
  & )

  ! 宣言文 ; Declaration statement
  !
  type(Field_Grid1D), intent(inout) :: self
  real(DP), intent(in) :: grid1D(:)
  character(*), intent(in) :: name
  integer, intent(in) :: rank

  ! 作業変数
  ! Work variables
  !

  ! 実行文 ; Executable statement
  !

  call init_Field_Grid1D0(self, grid1D, name, rank, '', '')

end subroutine init_Field_Grid1D2

subroutine Field_Grid1D_Final( &
  & self &  ! (inout)
  & )

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

  ! 実行文　; Executable statement
  !

!  write(*,*) 'Field_Grid1D finalize, name=', trim(get_name(self))

  ! 物理場データを保持している配列のメモリを解放する.
  deallocate(self%val)

  call Physical_Field_Final(self%base)

end subroutine Field_Grid1D_Final

function get_grid1D( &
  & self &  ! (inout)
  & ) result(grid1D)

  ! 宣言文 ; Declaration statement
  !
  type(Field_Grid1D), intent(in) :: self       !
  real(DP), pointer :: grid1D(:)

  ! 実行文 ; Executable statement
  !

  grid1D => self%grid1D

end function get_grid1D

!
!> \~japanese
!! \brief 構造型 Field_Grid1D の基底構造型 Physical_Field の変数へのポインタを取得する.
!!
!! @param[in,out] self 構造型 Field_Grid1D の変数.
!! @return 基底構造型 Physical_Field の変数へのポインタ.
!!
!! \~english
!! \brief Gets the pointer to a variable of derived type Physical_Field which is a base derived type of Field_Grid1D.
!!
!! @param[in,out] self A variable of derived type Field_Grid1D.
!! @return The pointer to a variable of base derived type  Physical_Field.
!!
function get_Physical_Field( &
  & self &  ! (inout)
  & ) result(val)

  ! 宣言文 ; Declaration statements
  !
  type(Field_Grid1D), intent(inout), target :: self
  type(Physical_Field), pointer :: val

  ! 実行文 ; Executable statements
  !
  val => self%base

end function get_Physical_Field

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! Physical_Field_mod の手続きをオーバライド
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


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

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

  ! 実行文 ; Executable statement
  !

  val = get_long_name_(self%base)

end function get_long_field1D_name

!
!> \~japanese
!! \brief 物理場の長い名前(あるいは解説文)を設定する.
!!
!! @param[in,out] self 構造型 Field_Grid1D の変数.
!! @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 Field_Grid1D.
!! @param[in] long_name The long name of (or explanation for) the physical field.
!!
subroutine set_long_field1D_name(self, long_name)
  ! 宣言文 ; Declaration statement
  !
  type(Field_Grid1D), intent(inout) :: self
  character(*), intent(in) ::  long_name

  ! 実行文 ; Executable statement
  !

  call set_long_name_(self%base, long_name)

end subroutine set_long_field1D_name

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

  ! 実行文 ; Executable statement
  !

  val = get_units_(self%base)

end function get_field1D_units

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

  ! 実行文 ; Executable statement
  !

  call set_units_(self%base, units)

end subroutine set_field1D_units

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

  ! 実行文 ; Executable statement
  !

  val = get_dimension_(self%base)

end function get_field1D_rank


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

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

  ! 実行文 ; Executable statement
  !

  name = get_name_(self%base)

end function get_field1D_name

!
!> \~japanese
!! \brief 物理場の(短い)名前を設定する.
!!
!! @param[in,out] self 構造型 Field_Grid1D の変数.
!! @param[in] name 物理場の(短い)名前.
!!
!! \~english
!! \brief Sets the (short) name of the physical field.
!!
!! @param[in,out] self The variable of derived type Field_Grid1D.
!! @param[in] name The (short) name of the physical field.
!!
subroutine set_field1D_name( &
  & self, name )

  ! 宣言文 ; Declaration statement
  !
  type(Field_Grid1D), intent(inout) :: self
  character(*), intent(in) ::  name

  ! 実行文 ; Executable statement
  !

  call set_name_(self%base, name)

end subroutine set_field1D_name

end module Field_Grid1D_Manager
