#!/usr/bin/env ruby
# -*- f90 -*-
# vi: set sw=4 ts=8:
require("intrinsic_types")
require("optparse")
#
# "gtvarputnum.f90" Generator with Ruby.
#
opt = OptionParser.new
opt.on('--gtvarput_dim=VAL') {|v| $gtvarput_dim = v.to_i}
opt.parse!(ARGV)
$gtvarput_dim = 7 unless $gtvarput_dim
print <<"__EndOfFortran90Code__"
!--
#{rb2f90_header_comment}!
!++
!
!= 変数への数値データの出力
!
! Authors::   Yasuhiro MORIKAWA, Eizi TOYODA
! Version::   $Id: gtvarputnum.rb2f90,v 1.5 2008-02-17 17:26:59 morikawa Exp $
! Tag Name::  $Name: gt4f90io-20080812 $
! Copyright:: Copyright (C) GFD Dennou Club, 2000-2005. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!
! 以下のサブルーチン、関数は gtdata_generic から gtdata_generic#Put
! として提供されます。
!
__EndOfFortran90Code__

types = ["Double", "Real", "Int"]
types.each{ |type|
print <<"__EndOfFortran90Code__"

subroutine GTVarPut#{type}(var, value, nvalue, err)
  !
#{ifelse(type, "Double", %Q{
  !
  !== 変数への数値データの出力
  !
  ! 変数 *var* へ数値データ *value* が出力されます。
  ! *nvalue* には配列長を代入する必要があります。
  !
  ! 数値データ出力の際にエラーが生じた場合、メッセージを出力
  ! してプログラムは強制終了します。*err* を与えてある場合には
  ! の引数に .true. が返り、プログラムは終了しません。
  !
  ! 出力しようとするデータの型が *var* の型と異なる場合、データは *var* の
  ! 型に変換されます。 この変換は netCDF の機能を用いています。
  ! 詳しくは {netCDF 日本語版マニュアル}[link:../xref.htm#label-10]
  ! の 3.3 型変換 を参照してください。
  !
  ! *Get* は複数のサブルーチンの総称名であり、
  ! *value* に多次元配列を与えることも可能です。上記の
  ! サブルーチンを参照してください。
  !
})}
  !
  use gtdata_types,only: GT_VARIABLE
  use gt_map,      only: var_class, vtb_class_netcdf, &
    &                    map_to_internal_specs
  use an_generic,  only: put, an_variable
  use dc_error,    only: StoreError, GT_EFAKE
  use dc_types,    only: DP
  use dc_trace,    only: BeginSub, EndSub
  implicit none
  type(GT_VARIABLE), intent(in)           :: var
  integer,           intent(in)           :: nvalue
  #{$type_intent_in[type]}, intent(in)           :: value(nvalue)
  logical,           intent(out), optional:: err

  ! Variables for Intenal work
  integer:: class, cid, stat, ndims
  integer, pointer:: specs(:, :)
  character(len = *), parameter:: subname = "GTVarPut#{type}"
continue
  call BeginSub(subname, 'var.mapid=%d', i=(/var%mapid/))
  call var_class(var, class, cid)
  call map_to_internal_specs(var, specs, ndims)
  if (class == vtb_class_netcdf) then
    call put(an_variable(cid), start=specs(:, 1), count=specs(:, 2), &
      & stride=specs(:, 3), imap=specs(:, 4), value=value, &
      & siz=nvalue, iostat=stat)
  else
    stat = gt_efake
  endif
  call StoreError(stat, subname, err=err)
  deallocate(specs)
  call EndSub(subname)
end subroutine GTVarPut#{type}

__EndOfFortran90Code__
}

types = ["Double", "Real", "Int"]
types.each{ |type|
for num in 1..$gtvarput_dim
print <<"__EndOfFortran90Code__"

subroutine GTVarPut#{type}#{num}(var, value, err)
  !
#{ifelse(num, 1, %Q{
#{ifelse(type, "Double", %Q{
  !
  !== 変数への数値データの出力
  !
  ! 変数 *var* へ数値データ *value* が出力されます。
  !
  ! 数値データ入力の際にエラーが生じた場合、メッセージを出力
  ! してプログラムは強制終了します。*err* を与えてある場合には
  ! の引数に .true. が返り、プログラムは終了しません。
  !
  ! 出力しようとするデータの型が *var* の型と異なる場合、データは *var* の
  ! 型に変換されます。 この変換は netCDF の機能を用いています。
  ! 詳しくは {netCDF 日本語版マニュアル}[link:../xref.htm#label-10]
  ! の 3.3 型変換 を参照してください。
  !
  ! *Get* は複数のサブルーチンの総称名であり、
  ! *value* には 1 〜 #{$gtvarput_dim} 次元の配列を与えることも可能です。
  ! 下記のサブルーチンを参照してください。
  !
})}
})}
  !
  use gtdata_types,   only: GT_VARIABLE
  use gtdata_generic, only: Put, GTVarPutReal, GTVarPutDouble, GTVarPutInt
  use dc_trace,    only: BeginSub, EndSub
  use dc_types,       only: DP
  type(GT_VARIABLE), intent(inout):: var
  #{$type_intent_in[type]}, intent(in) :: value#{array_colon("#{num}")}
  logical  ,intent(out), optional:: err
  character(len = *), parameter:: subname = "GTVarPut#{type}#{num}"
continue
  call BeginSub(subname, 'var.mapid=%d', i=(/var%mapid/))
  call GTVarPut#{type}(var, value, size(value), err)
  call EndSub(subname)
end subroutine GTVarPut#{type}#{num}

__EndOfFortran90Code__
end
}

print <<"__EndOfFooter__"
!--
! vi:set readonly sw=4 ts=8:
!
#{rb2f90_emacs_readonly}!
!++
__EndOfFooter__
