#!/usr/bin/env ruby
#
#= Fortran 90/95 dcmodel sample code maker
#
#Authors:: Yasuhiro MORIKAWA
#Version:: $Id: dcmodel_f90sample_maker.rb,v 1.75 2008-06-01 16:07:39 morikawa Exp $
#Tag Name:: $Name: dcpam4-20080626 $
#Copyright:: Copyright (C) GFD Dennou Club, 2007. All rights reserved.
#License:: See COPYRIGHT[link:../../COPYRIGHT]
#
#引数として受け取るキーワードに応じ, {dcmodel プログラミングガイドライン}[http://www.gfd-dennou.org/library/dcmodel/coding-rules/dcmodel-coding-rules.htm]
#に基づく Fortran 90/95 ソースコードの雛形となるコードをファイルに書き出す.
#
require "optparse"
#
# {dcmodel プログラミングガイドライン}[http://www.gfd-dennou.org/library/dcmodel/coding-rules/dcmodel-coding-rules.htm]に基づく
# Fortran 90/95 ソースコードの雛形となるコードを生成するためのクラス.
#
class DCModelF90SampleMaker
#
#作成するコードの種類に応じ, 第1引数 *entity* には
#'module' (モジュール全体), 'procedure' (手続), 'type' (構造型定義)
#を与える. 第1引数に 'procedure' を与えた場合のみ, 第2引数 *proc_kind*
#が有効となり, ここに手続きの種類を与える. 詳しくは
#DCModelF90SampleMaker を参照のこと.
#
#現在, 第3引数は無効.
#
def initialize(entity, proc_kind='sample', quiet=nil)
case entity
when 'module'
@entity = DCModelF90SampleModuleMaker.new
@test = DCModelF90SampleTestMaker.new
@testnml = DCModelF90SampleTestNmlMaker.new
@testsh = DCModelF90SampleTestShMaker.new
when 'procedure'
@entity = DCModelF90SampleProcMaker.new(proc_kind)
when 'type'
@entity = DCModelF90SampleTypeMaker.new
else
raise ArgumentError, " Error: @entity = \"#{entity}\" is invalid."
end
end
#
# このメソッドを呼び出すと, コマンドライン上で
# インタラクティブに設定が行われる.
#
def interactive_setup
@entity.interactive_setup
end
#
# ファイル名としてふさわしい名前を返す.
#
def filename
return @entity.filename
end
#
# テストファイル名としてふさわしい名前を返す.
# ただし, モジュール全体を生成する場合以外は空文字を返す.
#
def test_filename
if @test
@test.set_modname(@entity.mod_name)
return @test.filename
else
return ''
end
end
#
# テスト用 NAMELIST ファイル名としてふさわしい名前を返す.
# ただし, モジュール全体を生成する場合以外は空文字を返す.
#
def testnml_filename
if @testnml
@testnml.set_modname(@entity.mod_name)
return @testnml.filename
else
return ''
end
end
#
# テスト実行用シェルスクリプトファイル名としてふさわしい名前を返す.
# ただし, モジュール全体を生成する場合以外は空文字を返す.
#
def testsh_filename
if @testsh
@testsh.set_modname(@entity.mod_name)
return @testsh.filename
else
return ''
end
end
#
# 日本語ドキュメントが不要な場合にこのメソッドを呼ぶ
#
def no_lang_ja
@entity.lang_ja = false
end
#
# F90 ソースコードを返す.
#
def to_s
return @entity.to_s
end
#
# テストプログラムのソースコードを返す.
# ただし, モジュール全体を生成する場合以外は空文字を返す.
#
def test_to_s
if @test
@test.set_modname(@entity.mod_name)
@test.set_basename(@entity.mod_basename)
@test.set_arg_type(@entity.mod_arg_type)
@test.set_arg_keyword(@entity.mod_arg_keyword)
@test.set_author(@entity.author)
@test.set_copyright(@entity.copyright)
@test.lang_ja = @entity.lang_ja
return @test.to_s
else
return ''
end
end
#
# テストプログラム用 NAMELIST ファイルの中身を返す.
# ただし, モジュール全体を生成する場合以外は空文字を返す.
#
def testnml_to_s
if @testnml
@testnml.set_modname(@entity.mod_name)
@testnml.set_author(@entity.author)
@testnml.set_copyright(@entity.copyright)
@testnml.lang_ja = @entity.lang_ja
return @testnml.to_s
else
return ''
end
end
#
# テストプログラム実行用シェルスクリプトファイルの中身を返す.
# ただし, モジュール全体を生成する場合以外は空文字を返す.
#
def testsh_to_s
if @testsh
@testsh.set_modname(@entity.mod_name)
@testsh.set_author(@entity.author)
@testsh.set_copyright(@entity.copyright)
@testsh.lang_ja = @entity.lang_ja
return @testsh.to_s
else
return ''
end
end
#
# DCModelF90SampleMaker クラス内で使用する共通メソッドを用意.
#
module F90CodeChecker
#
# 第1引数 name が Fortran 90/95 ソースコードの言語要素として使用できる
# 名称かどうかをチェックする. 使用できる場合には true を, 使用できない場合
# には false を返す.
# 第2引数 raiseerror に true を与える場合, name が言語要素の名称として
# 不適切な場合, エラーを生じる.
#
def valid_f90entityname?(name, raiseerror=nil)
f90entityname = /^[A-Za-z][A-Za-z0-9_]*$/
unless name && name.to_s =~ f90entityname
if raiseerror
raise ArgumentError, " Error: \"#{name.to_s}\" is invalid for f90 entity name."
else
return false
end
end
return true
end
#
# 標準入力から F90 ソースコードの言語要素の名称を受け取る.
# 第1引数 defaultname にはデフォルト値を (無入力の場合はこれを受け取る),
# 第2引数には受け取る値の解説文を与える.
#
# 入力された値が不適切である場合, 何度も入力を求める.
#
def f90entityname_from_stdin(defaultname, keyword)
getname = ''
while !(valid_f90entityname?(getname))
print " Input #{keyword} [#{defaultname}]: "
getname = STDIN.gets.chomp
getname = defaultname if getname == ''
end
return getname
end
end
#
# {dcmodel プログラミングガイドライン}[http://www.gfd-dennou.org/library/dcmodel/coding-rules/dcmodel-coding-rules.htm]に基づく
# Fortran 90/95 ソースコード (モジュール) の雛形となる
# コードを生成するためのクラス.
#
class DCModelF90SampleModuleMaker
include F90CodeChecker
attr_reader :mod_name, :mod_basename, :mod_arg_type, :mod_arg_keyword
attr_reader :author, :copyright
attr_accessor :lang_ja
def initialize(quiet=nil)
@mod_name = 'dcmodel_sample_code'
autoset_names
@quiet = quiet
@author = 'unknown'
@copyright = 'GFD Dennou Club'
@title = 'Title'
@title_ja = 'タイトル'
@lang_ja = true
end
#
# ファイル名としてふさわしい名前を返す.
#
def filename
return @mod_name.tr("A-Z","a-z") + '.f90'
end
def set_modname(modname)
valid_f90entityname?(modname, true)
@mod_name = modname.to_s
end
#
# @mod_name を元に, 自動的に手続きの名前のベースネームや
# 構造体名, 個々の手続き用の引数キーワード名を作成する.
# @mod_name はいくつかの単語 (小文字) をアンダーバーで繋いだ
# 文字列であることが仮定されている.
#
def autoset_names
return false unless @mod_name =~ /.+\_.+/
@mod_basename = ''
@mod_arg_type = ''
@mod_arg_keyword = ''
@mod_name.split('_').each{ |part|
@mod_basename << part.sub(/^./){|c| c.tr("a-z","A-Z")}
[part.length, 3].min.times{|i|
@mod_arg_type << part[i].chr.tr("a-z","A-Z")
@mod_arg_keyword << part[i].chr.tr("A-Z","a-z")
}
@mod_arg_keyword << '_'
}
@mod_arg_keyword.sub!(/\_+$/, '')
return true
end
#
# このメソッドを呼び出すと, コマンドライン上で
# インタラクティブに設定が行われる.
#
def interactive_setup
@mod_name = f90entityname_from_stdin(@mod_name, 'Module name')
autoset_names
print " Title of module (for English documentation) [#{@title}]: "
title = STDIN.gets.chomp
@title = title unless title == ''
if @lang_ja
print " Title of module (for Japanese documentation) [#{@title_ja}]: "
title_ja = STDIN.gets.chomp
@title_ja = title_ja unless title_ja == ''
end
@mod_basename = f90entityname_from_stdin(@mod_basename, 'basename')
@mod_arg_type = f90entityname_from_stdin(@mod_arg_type, 'arg_type')
if @mod_name == @mod_arg_type
raise ArgumentError,
"\n Error: Module name \"#{@mod_name}\" is equal to arg_type \"#{@mod_arg_type}\" ."
end
@mod_arg_keyword = f90entityname_from_stdin(@mod_arg_keyword, 'arg_keyword')
if @mod_arg_type == @mod_arg_keyword
raise ArgumentError,
"\n Error: arg_type \"#{@mod_arg_type}\" is equal to arg_keyword \"#{@mod_arg_keyword}\" ."
# elsif @mod_name == @mod_arg_keyword
# raise ArgumentError,
# "\n Error: Module name \"#{@mod_name}\" is equal to arg_keyword \"#{@mod_arg_keyword}\" ."
end
print " Input Your name [#{@author}]: "
author = STDIN.gets.chomp
@author = author unless author == ''
print " Input Copyright [#{@copyright}]: "
copyright = STDIN.gets.chomp
@copyright = copyright unless copyright == ''
end
#
# F90 ソースコードを返す.
#
def to_s
str = ''
str << <<-EOF
!= #{@title_ja}
!
!= #{@title}
!
! Authors:: #{@author}
! Version:: $#{}I#{}d: $
! Tag Name:: $#{}N#{}ame: $
! Copyright:: Copyright (C) #{@copyright}, #{Time.now.strftime("%Y")}. All rights reserved.
! License::
!
module #{@mod_name}
!
!= #{@title_ja}
!
!= #{@title}
!
! Note that Japanese and English are described in parallel.
!
! モジュールに関する概説
!
! Overview of Modules
!
!== Procedures List
!
! #{@mod_basename}Create :: #{@mod_arg_type} 型変数の初期設定
! #{@mod_basename}Calculation :: 演算
! #{@mod_basename}Close :: #{@mod_arg_type} 型変数の終了処理
! #{@mod_basename}PutLine :: #{@mod_arg_type} 型変数に格納されている情報の印字
! #{@mod_basename}initialized :: #{@mod_arg_type} 型変数が初期設定されているか否か
! #{@mod_basename}SetTime :: 時刻の設定
! ------------ :: ------------
! #{@mod_basename}Create :: Constructor of "#{@mod_arg_type}"
! #{@mod_basename}Calculation :: Calculation
! #{@mod_basename}Close :: Deconstructor of "#{@mod_arg_type}"
! #{@mod_basename}PutLine :: Print information of "#{@mod_arg_type}"
! #{@mod_basename}initialized :: Check initialization of "#{@mod_arg_type}"
! #{@mod_basename}SetTime :: Configure time
!
!== Usage
!
! 始めに, #{@mod_arg_type} 型の変数を定義し,
! #{@mod_basename}Create で初期設定を行います.
!--
! モジュールの利用法を記述してください.
!++
! #{@mod_arg_type} 型の変数の終了処理には
! #{@mod_basename}Close を用いてください.
!
! First, initialize "#{@mod_arg_type}" by "#{@mod_basename}Create".
!--
! Describe usage of module
!++
! In order to terminate "#{@mod_arg_type}", use "#{@mod_basename}Close".
!
use dc_types, only: DP, TOKEN, STRING
use dc_date_types, only: DC_DIFFTIME
use gt4_history_nmlinfo, only: GTHST_NMLINFO
implicit none
private
public:: #{@mod_arg_type}
public:: #{@mod_basename}Create, #{@mod_basename}Calculation
public:: #{@mod_basename}Close, #{@mod_basename}PutLine
public:: #{@mod_basename}Initialized, #{@mod_basename}SetTime
EOF
typemake = DCModelF90SampleTypeMaker.new
typemake.lang_ja = @lang_ja
typemake.set_typename(@mod_arg_type)
typemake.set_modname(@mod_name)
typemake.set_basename(@mod_basename)
str << typemake.to_s
str << "\n"
str << <<-EOF
character(*), parameter:: version = &
& '$Name: dcpam4-20080626 $' // &
& '$#{}I#{}d: $'
EOF
str << <<-EOF
!-----------------------------------------------------------------
! 公開手続
! Public procedures
!-----------------------------------------------------------------
EOF
proc_public_list = ['create', 'calc', 'sample', 'close', 'putline', 'initialized', 'settime']
proc_private_list = ['nmlread']
proc_public_list.each {|proc|
if !(proc == 'initialized') && !(proc == 'sample')
proc_name = proc.sub(/^./){|c| c.tr("a-z","A-Z")}
proc_name = 'PutLine' if proc_name == 'Putline'
proc_name = 'SetTime' if proc_name == 'Settime'
proc_name = 'Calculation' if proc_name == 'Calc'
str << <<-EOF
interface #{@mod_basename}#{proc_name}
module procedure #{@mod_basename}#{proc_name}
end interface
EOF
elsif proc == 'initialized'
# proc_name = proc.sub(/^./){|c| c.tr("a-z","A-Z")}
proc_name = 'Initialized'
str << <<-EOF
interface #{@mod_basename}#{proc}
module procedure #{@mod_basename}#{proc_name}
end interface
EOF
elsif proc == 'sample'
proc_name = 'Sample'
str << <<-EOF
!!$ interface #{@mod_basename}#{proc_name}
!!$ module procedure #{@mod_basename}#{proc_name}
!!$ end interface
EOF
end
}
str << <<-EOF
!-----------------------------------------------------------------
! 非公開手続
! Private procedures
!-----------------------------------------------------------------
EOF
proc_private_list.each {|proc|
if !(proc == 'sample')
proc_name = proc.sub(/^./){|c| c.tr("a-z","A-Z")}
proc_name = 'NmlRead' if proc_name == 'Nmlread'
str << <<-EOF
interface #{proc_name}
module procedure #{@mod_basename}#{proc_name}
end interface
EOF
else
proc_name = 'Sample'
str << <<-EOF
!!$ interface #{@mod_basename}#{proc_name}
!!$ module procedure #{@mod_basename}#{proc_name}
!!$ end interface
EOF
end
}
str << <<-EOF
contains
EOF
proc_list = proc_public_list + proc_private_list
proc_list.each {|proc|
procmake = DCModelF90SampleProcMaker.new(proc)
procmake.lang_ja = @lang_ja
procmake.set_modname(@mod_name)
procmake.set_basename(@mod_basename)
procmake.set_arg_type(@mod_arg_type)
procmake.set_arg_keyword(@mod_arg_keyword)
unless proc == 'sample'
str << procmake.to_s
str << "\n"
else
procmake.set_operate_name('Sample')
str << procmake.to_s.gsub(/^/, '!!$')
str << "\n"
end
}
str << <<-EOF
end module #{@mod_name}
EOF
if @lang_ja
return str.gsub(/\n?/m, '').gsub(/<\/ja>\n?/m, '')
else
return str.gsub(/.*?<\/ja>\n?/m, '')
end
end
end
#
# {dcmodel プログラミングガイドライン}[http://www.gfd-dennou.org/library/dcmodel/coding-rules/dcmodel-coding-rules.htm]に基づく
# Fortran 90/95 ソースコード (構造型定義) の雛形となる
# コードを生成するためのクラス.
#
class DCModelF90SampleTypeMaker
include F90CodeChecker
attr_accessor :lang_ja
def initialize(quiet=nil)
@type_name = 'DCSMPLCODE'
@lang_ja = true
@mod_name = 'dcmodel_sample_code' # used for '***_HISTNML' type
end
#
# ファイル名としてふさわしい名前を返す.
#
def filename
return @type_name.tr("A-Z","a-z") + '.f90'
end
def set_typename(typename)
valid_f90entityname?(typename, true)
@type_name = typename.to_s
end
def set_modname(modname)
valid_f90entityname?(modname, true)
@mod_name = modname.to_s
end
def set_basename(basename)
valid_f90entityname?(basename, true)
@basename = basename.to_s
end
#
# このメソッドを呼び出すと, コマンドライン上で
# インタラクティブに設定が行われる.
#
def interactive_setup
@type_name = f90entityname_from_stdin(@type_name, 'type_name')
end
#
# F90 ソースコードを返す.
#
def to_s
str = <<-EOF
type #{@type_name}
!
! まず, #{@basename}Create で "#{@type_name}" 型の
! 変数を初期設定して下さい.
! 初期設定された "#{@type_name}" 型の変数を再度利用する際には,
! #{@basename}Close によって終了処理を行ってください.
!
! Initialize "#{@type_name}" variable by
! "#{@basename}Create" before usage.
! If you reuse "#{@type_name}" variable again for another application,
! terminate by "#{@basename}Close".
!
logical:: initialized = .false.
! 初期設定フラグ.
! Initialization flag
!-----------------------------------------------------------------
! 格子点数・最大全波数
! Grid points and maximum truncated wavenumber
!-----------------------------------------------------------------
!!$ integer:: imax ! 経度格子点数.
!!$ ! Number of grid points in longitude
!!$ integer:: jmax ! 緯度格子点数.
!!$ ! Number of grid points in latitude
!-----------------------------------------------------------------
! 軸データ
! Axes data
!-----------------------------------------------------------------
!!$ real(DP), pointer:: x_Lon (:) =>null()
!!$ ! 経度. Longitude
!!$ real(DP), pointer:: y_Lat (:) =>null()
!!$ ! 緯度. Latitude
!-----------------------------------------------------------------
! 係数
! Coefficients
!-----------------------------------------------------------------
!!$ real(DP):: CoefAlpha ! $ \\alpha $ . 係数. Coefficient
!-----------------------------------------------------------------
! 文字データ
! Character data
!-----------------------------------------------------------------
!!$ character(TOKEN):: key00 ! キーワード. Keyword
!!$
!-----------------------------------------------------------------
! 時刻管理
! Time control
!-----------------------------------------------------------------
type(DC_DIFFTIME):: current_time
! 現在時刻. Current time.
type(DC_DIFFTIME):: delta_time
! $ \\Delta t $ . タイムステップ. Time step
!-----------------------------------------------------------------
! ヒストリファイルへのデータ出力設定
! Configure the settings for history data output
!-----------------------------------------------------------------
type(GTHST_NMLINFO):: gthstnml
! NAMELIST\##{@mod_name}_history_nml
! から入手される個別のデータ出力情報.
!
! Individual data output information from
! "NAMELIST\##{@mod_name}_history_nml".
end type #{@type_name}
EOF
if @lang_ja
return str.gsub(/\n?/m, '').gsub(/<\/ja>\n?/m, '')
else
return str.gsub(/.*?<\/ja>\n?/m, '')
end
end
end
#
# {dcmodel プログラミングガイドライン}[http://www.gfd-dennou.org/library/dcmodel/coding-rules/dcmodel-coding-rules.htm]に基づく
# Fortran 90/95 ソースコード (手続き) の雛形となる
# コードを生成するためのクラス.
#
class DCModelF90SampleProcMaker
include F90CodeChecker
attr_accessor :lang_ja
def initialize(kind='sample', quiet=nil)
case kind
when 'create', 'close', 'putline', 'initialized', 'settime', 'calc', 'nmlread', 'sample'
@kind = kind
else
raise ArgumentError, " Error: @kind = \"#{kind}\" is invalid."
end
case kind
when 'create', 'close', 'initialized'
@operate_name = kind.sub(/^./){|c| c.tr("a-z","A-Z")}
when 'putline'
@operate_name = 'PutLine'
when 'settime'
@operate_name = 'SetTime'
when 'calc'
@operate_name = 'Calculation'
when 'nmlread'
@operate_name = 'NmlRead'
else
@operate_name = 'Sample'
end
@basename = 'DcmodelSampleCode'
@arg_type = 'DCMSAMCOD'
@arg_keyword = 'dcm_sam_cod'
@alreadyinit_err_code = 'DC_EALREADYINIT'
@noinit_err_code = 'DC_ENOTINIT'
@quiet = quiet
@lang_ja = true
@mod_name = 'dcmodel_sample_code' # used for 'nmlread'
end
#
# ファイル名としてふさわしい名前を返す.
#
def filename
return (@basename + @operate_name).tr("A-Z","a-z") + '.f90'
end
#
# このメソッドを呼び出すと, コマンドライン上で
# インタラクティブに設定が行われる.
#
def interactive_setup
case @kind
when 'nmlread'
@mod_name = f90entityname_from_stdin(@mod_name, 'modname')
end
@basename = f90entityname_from_stdin(@basename, 'basename')
@operate_name = f90entityname_from_stdin(@operate_name, 'operate_name')
@arg_type = f90entityname_from_stdin(@arg_type, 'arg_type')
@arg_keyword = f90entityname_from_stdin(@arg_keyword, 'arg_keyword')
@noinit_err_code = f90entityname_from_stdin(@noinit_err_code, 'noinit_err_code')
@alreadyinit_err_code = f90entityname_from_stdin(@alreadyinit_err_code, 'alreadyinit_err_code')
end
def set_modname(modname)
valid_f90entityname?(modname, true)
@mod_name = modname.to_s
end
def set_basename(basename)
valid_f90entityname?(basename, true)
@basename = basename.to_s
end
def set_operate_name(operate_name)
valid_f90entityname?(operate_name, true)
@operate_name = operate_name.to_s
end
def set_arg_type(arg_type)
valid_f90entityname?(arg_type, true)
@arg_type = arg_type.to_s
end
def set_arg_keyword(arg_keyword)
valid_f90entityname?(arg_keyword, true)
@arg_keyword = arg_keyword.to_s
end
def set_noinit_err_code(noinit_err_code)
valid_f90entityname?(noinit_err_code, true)
@noinit_err_code = noinit_err_code.to_s
end
def set_alreadyinit_err_code(alreadyinit_err_code)
valid_f90entityname?(alreadyinit_err_code, true)
@alreadyinit_err_code = alreadyinit_err_code.to_s
end
#
# F90 ソースコードを返す. 設定値が無効な場合, 空文字を返す.
#
def to_s
str = ''
case @kind
when 'create', 'close', 'putline', 'initialized', 'settime', 'calc', 'nmlread', 'sample'
case @kind
when 'putline'
str = <<-EOF
subroutine #{@basename}#{@operate_name}( #{@arg_keyword}, unit, indent, err )
EOF
when 'create'
str = <<-EOF
subroutine #{@basename}#{@operate_name}( #{@arg_keyword}, &
!!$ & imax, jmax, &
!!$ & x_Lon, y_Lat, &
!!$ & CoefAlpha, DelTime, &
& current_time_value, current_time_unit, &
& history_varlist, &
& history_interval_value, history_interval_unit, &
& history_precision, history_fileprefix, &
& nmlfile, err )
EOF
when 'initialized'
str = <<-EOF
logical function #{@basename}#{@operate_name}( #{@arg_keyword} ) result(result)
EOF
when 'settime'
str = <<-EOF
subroutine #{@basename}#{@operate_name}( #{@arg_keyword}, &
& current_time_value, current_time_unit, &
& err )
EOF
when 'calc'
str = <<-EOF
subroutine #{@basename}#{@operate_name}( #{@arg_keyword}, &
!!$ & x_Data1, y_Data2, &
& historyput_flag, &
& err )
EOF
when 'nmlread'
str = <<-EOF
subroutine #{@basename}#{@operate_name}( nmlfile, &
!!$ & CoefAlpha, &
!!$ & key00_, &
& gthstnml, &
& err )
EOF
else
str = <<-EOF
subroutine #{@basename}#{@operate_name}( #{@arg_keyword}, err )
EOF
end
case @kind
when 'initialized'
str << <<-EOF
#{dc_default_documentation}
#{dc_default_declaration}
continue
#{dc_default_operate}
end function #{@basename}#{@operate_name}
EOF
else
str << <<-EOF
#{dc_default_documentation}
#{dc_default_declaration}
character(*), parameter:: subname = '#{@basename}#{@operate_name}'
continue
#{dc_default_preinit}
#{dc_default_initialize}
#{dc_default_operate}
#{dc_default_terminate}
#{dc_default_internal_procedures}
end subroutine #{@basename}#{@operate_name}
EOF
end
else
return ''
end
if @lang_ja
return str.gsub(/\n?/m, '').gsub(/<\/ja>\n?/m, '')
else
return str.gsub(/.*?<\/ja>\n?/m, '')
end
end
def dc_default_documentation
str = ''
case @kind
when 'create'
str << <<-EOF
!
! #{@arg_type} 型の変数の初期設定を行います.
! 他のサブルーチンを使用する前に必ずこのサブルーチンによって
! #{@arg_type} 型の変数を初期設定してください.
!
! なお, 与えられた *#{@arg_keyword}* が既に初期設定されている場合,
! プログラムはエラーを発生させます.
!
! NAMELIST を利用する場合には引数 *nmlfile* に NAMELIST ファイル名
! を与えてください. NAMELIST 変数群の詳細に関しては
! NAMELIST\##{@mod_name}_nml を参照してください.
!
! Constructor of "#{@arg_type}".
! Initialize *#{@arg_keyword}* by this subroutine,
! before other procedures are used,
!
! Note that if *#{@arg_keyword}* is already initialized
! by this procedure, error is occurred.
!
! In order to use NAMELIST, specify a NAMELIST filename to
! argument *nmlfile*. See "NAMELIST\##{@mod_name}_nml"
! for details about a NAMELIST group.
!
EOF
when 'close'
str << <<-EOF
!
! #{@arg_type} 型の変数の終了処理を行います.
! なお, 与えられた *#{@arg_keyword}* が #{@basename}Create
! によって初期設定されていない場合, プログラムはエラーを発生させます.
!
! Deconstructor of "#{@arg_type}".
! Note that if *#{@arg_keyword}* is not initialized
! by "#{@basename}Create" yet, error is occurred.
!
EOF
when 'putline'
str << <<-EOF
!
! 引数 *#{@arg_keyword}* に設定されている情報を印字します.
! デフォルトではメッセージは標準出力に出力されます.
! *unit* に装置番号を指定することで, 出力先を変更することが可能です.
!
! Print information of *#{@arg_keyword}*.
! By default messages are output to standard output.
! Unit number for output can be changed by *unit* argument.
!
EOF
when 'initialized'
str << <<-EOF
!
! *#{@arg_keyword}* が初期設定されている場合には .true. が,
! 初期設定されていない場合には .false. が返ります.
!
! If *#{@arg_keyword}* is initialized, .true. is returned.
! If *#{@arg_keyword}* is not initialized, .false. is returned.
!
EOF
when 'settime'
str << <<-EOF
!
! *#{@arg_keyword}* に対して時刻の設定を行います.
!
! ヒストリデータを出力している場合には,
! ヒストリデータの出力時刻も設定します.
! 一度でもこのサブルーチンを呼んだ場合には,
! それ以後のヒストリデータ出力前にこのサブルーチンを呼び出し,
! 時刻の設定を行ってください.
! また, データを出力するサブルーチンに対しても
! オプショナル引数 historyput_flag に .true. を与えてください.
!
! なお, 与えられた *#{@arg_keyword}* が #{@basename}Create
! によって初期設定されていない場合, プログラムはエラーを発生させます.
!
! Set time to *#{@arg_keyword}*.
!
! When history data are output,
! the output time of history data are specified.
! Once this subroutine is called, the time of history data must be
! specified by this routine before history data output.
! In additional, give ".true." to an optional argument
! "historyput_flag" of a data output subroutine.
!
! If *#{@arg_keyword}* is not initialized
! by "#{@basename}Create" yet, error is occurred.
!
EOF
when 'calc'
str << <<-EOF
!
! *x_Data1* と *y_Data2* に対して演算を行い, 変更された値を返します.
! 計算後, *#{@arg_keyword}* 内の時刻を更新します.
!
! なお, 与えられた *#{@arg_keyword}* が #{@basename}Create
! によって初期設定されていない場合, プログラムはエラーを発生させます.
!
! Calculate *x_Data1* and *y_Data2*, and return changed values.
! After the calculation, time stored in *#{@arg_keyword}* is updated.
!
! If *#{@arg_keyword}* is not initialized
! by "#{@basename}Create" yet, error is occurred.
!
EOF
when 'nmlread'
str << <<-EOF
!
! NAMELIST ファイル *nmlfile* から値を入力するための
! サブルーチンです. #{@basename}Create
! 内で呼び出されることを想定しています.
!
! 値が NAMELIST ファイル内で指定されていない場合には,
! 入力された値がそのまま返ります.
!
! なお, *nmlfile* に空文字が与えられた場合, または
! 与えられた *nmlfile* を読み込むことができない場合,
! プログラムはエラーを発生させます.
!
! This is a subroutine to input values from
! NAMELIST file *nmlfile*. This subroutine is expected to be
! called by "#{@basename}Create".
!
! A value not specified in NAMELIST file is returned
! without change.
!
! If *nmlfile* is empty, or *nmlfile* can not be read,
! error is occurred.
!
EOF
else
str << <<-EOF
!--
! #{@basename}#{@operate_name} の要約を記述してください.
!++
! なお, 与えられた *#{@arg_keyword}* が #{@basename}Create
! によって初期設定されていない場合, プログラムはエラーを発生させます.
!--
! Describe brief of "#{@basename}#{@operate_name}".
!++
! If *#{@arg_keyword}* is not initialized
! by "#{@basename}Create" yet, error is occurred.
!
EOF
end
return str.chomp
end
def dc_default_declaration
case @kind
when 'initialized'
str = <<-EOF
implicit none
type(#{@arg_type}), intent(in):: #{@arg_keyword}
EOF
return str.chomp
end
str = <<-EOF
use dc_trace, only: BeginSub, EndSub
use dc_string, only: PutLine, Printf, Split, StrInclude, StoA, JoinChar
use dc_types, only: DP, STRING, TOKEN, STDOUT
EOF
case @kind
when 'create'
str << <<-EOF
use dc_present, only: present_and_not_empty, present_and_true, &
& present_select
use dc_message, only: MessageNotify
use dc_error, only: StoreError, DC_NOERR, #{@alreadyinit_err_code}, &
& DC_EARGLACK, DC_ENEGATIVE, DC_ENOFILEREAD, USR_ERRNO, HST_EBADVARNAME
use dc_date, only: DCDiffTimeCreate
use dc_hash, only: HASH, DCHashPut, DCHashRewind, DCHashNext, DCHashDelete
use gt4_history_nmlinfo, only: HstNmlInfoCreate, HstNmlInfoAdd, &
& HstNmlInfoEndDefine, HstNmlInfoPutLine, HstNmlInfoAllNameValid
use gt4_history, only: GT_HISTORY, &
& HistoryAddVariable, HistoryAddAttr
EOF
when 'calc'
str << <<-EOF
use dc_present, only: present_and_true
use dc_date, only: mod, operator(+), operator(==), EvalbyUnit, EvalSec
use dc_error, only: StoreError, DC_NOERR, #{@noinit_err_code}, USR_ERRNO
use gt4_history_nmlinfo, only: HstNmlInfoInquire, &
& HstNmlInfoOutputValid, HstNmlInfoAssocGtHist, HstNmlInfoPutLine
use gt4_history, only: GT_HISTORY, HistoryPut, HistoryInitialized
EOF
when 'close'
str << <<-EOF
use dc_error, only: StoreError, DC_NOERR, #{@noinit_err_code}
use gt4_history_nmlinfo, only: HstNmlInfoClose, HstNmlInfoNames, &
& HstNmlInfoAssocGtHist, HstNmlInfoPutLine
use gt4_history, only: GT_HISTORY, HistoryClose, HistoryInitialized
EOF
when 'putline'
str << <<-EOF
use dc_date, only: EvalSec
use dc_error, only: StoreError, DC_NOERR, #{@noinit_err_code}
use gt4_history_nmlinfo, only: GTHST_NMLINFO, HstNmlInfoPutLine
EOF
when 'settime'
str << <<-EOF
use dc_date, only: DCDiffTimeCreate, EvalbyUnit
use dc_error, only: StoreError, DC_NOERR, #{@noinit_err_code}
use gt4_history_nmlinfo, only: HstNmlInfoAdd, HstNmlInfoInquire, &
& HstNmlInfoNames, HstNmlInfoAssocGtHist, &
& HstNmlInfoOutputStepDisable, HstNmlInfoPutLine
use gt4_history, only: GT_HISTORY, HistorySetTime, HistoryInitialized
EOF
when 'nmlread'
str << <<-EOF
use dc_iounit, only: FileOpen
use dc_message, only: MessageNotify
use dc_present, only: present_and_true
use dc_date, only: DCDiffTimeCreate
use dc_error, only: StoreError, DC_NOERR, DC_ENOFILEREAD, #{@noinit_err_code}
use gt4_history_nmlinfo, only: GTHST_NMLINFO, HstNmlInfoAdd, &
& HstNmlInfoInquire, HstNmlInfoInitialized, HstNmlInfoPutLine
EOF
else
str << <<-EOF
use dc_date, only: EvalSec
use dc_error, only: StoreError, DC_NOERR, #{@noinit_err_code}
EOF
end
str << <<-EOF
implicit none
EOF
case @kind
when 'putline'
str << <<-EOF
type(#{@arg_type}), intent(in):: #{@arg_keyword}
EOF
when 'nmlread'
else
str << <<-EOF
type(#{@arg_type}), intent(inout):: #{@arg_keyword}
EOF
end
case @kind
when 'create'
str << <<-EOF
!!$ integer, intent(in):: imax
!!$ ! 経度格子点数.
!!$ ! Number of grid points in longitude
!!$ integer, intent(in):: jmax
!!$ ! 緯度格子点数.
!!$ ! Number of grid points in latitude
!!$ real(DP), intent(in):: x_Lon (0:imax-1)
!!$ ! 経度. Longitude
!!$ real(DP), intent(in):: y_Lat (0:jmax-1)
!!$ ! 緯度. Latitude
!!$ real(DP), intent(in):: CoefAlpha
!!$ ! $ \\alpha $ . 係数. Coefficient
!!$ real(DP), intent(in):: DelTime
!!$ ! $ \\Delta t $ . タイムステップ. Time step
real, intent(in), optional:: current_time_value
! 現在時刻の数値. Numerical value of current time
character(*), intent(in), optional:: current_time_unit
! 現在時刻の単位. Unit of current time
character(*), intent(in), optional:: history_varlist
! ヒストリデータの出力変数リスト.
! カンマで区切って並べる.
! (例: "Data1,Data2" ).
!
! List of variables output to history data.
! Delimiter is comma.
! (exp. "Data1,Data2" ).
!
real, intent(in), optional:: history_interval_value
! ヒストリデータの出力間隔の数値.
! Numerical value for interval of history data output
character(*), intent(in), optional:: history_interval_unit
! ヒストリデータの出力間隔の単位.
! Unit for interval of history data output
character(*), intent(in), optional:: history_precision
! ヒストリデータの精度.
! Precision of history data
character(*), intent(in), optional:: history_fileprefix
! ヒストリデータのファイル名の接頭詞.
! Prefix of history data filenames
character(*), intent(in), optional:: nmlfile
! NAMELIST ファイルの名称.
! この引数に空文字以外を与えた場合,
! 指定されたファイルから
! NAMELIST 変数群を読み込みます.
! ファイルを読み込めない場合にはエラーを
! 生じます.
!
! NAMELIST 変数群の詳細に関しては
! NAMELIST\##{@mod_name}_nml
! を参照してください.
!
! NAMELIST file name.
! If nonnull character is specified to
! this argument,
! NAMELIST group name is loaded from the
! file.
! If the file can not be read,
! an error occurs.
!
! See "NAMELIST\##{@mod_name}_nml"
! for details about a NAMELIST group.
!
EOF
when 'putline'
str << <<-EOF
integer, intent(in), optional:: unit
! 出力先の装置番号.
! デフォルトの出力先は標準出力.
!
! Unit number for output.
! Default value is standard output.
character(*), intent(in), optional:: indent
! 表示されるメッセージの字下げ.
!
! Indent of displayed messages.
EOF
when 'settime'
str << <<-EOF
real, intent(in):: current_time_value
! 現在時刻の数値. Numerical value of current time
character(*), intent(in):: current_time_unit
! 現在時刻の単位. Unit of current time
EOF
when 'calc'
str << <<-EOF
!!$ real(DP), intent(inout):: x_Data1 (0:#{@arg_keyword}%imax-1)
!!$ ! データ 1. Data 1
!!$ real(DP), intent(inout):: y_Data2 (0:#{@arg_keyword}%jmax-1)
!!$ ! データ 2. Data 2
logical, intent(in), optional:: historyput_flag
! データ出力のフラグ.
! SetTime によって時刻を明示的に
! 指定した場合には, この引数に
! .true. または .false. を指定する
! ことでデータ出力のオンオフを
! 明示的に指定する必要があります.
! デフォルトは .false. です.
!
! Data output flag.
! When time is specified by "SetTime",
! explicit specification of data output
! on/off by specifying ".true." or ".false."
! to this argument.
! Default value is ".false.".
!
EOF
when 'nmlread'
str << <<-EOF
character(*), intent(in):: nmlfile
! NAMELIST ファイルの名称.
! NAMELIST file name
!!$ real(DP), intent(inout):: CoefAlpha
!!$ ! $ \\alpha $ . 係数. Coefficient
!!$
!!$ character(*), intent(inout):: key00_
!!$ character(TOKEN):: key00
!!$ ! キーワード. Keyword
!!$
type(GTHST_NMLINFO), intent(inout):: gthstnml
! NAMELIST\##{@mod_name}_history_nml
! から入手される個別のデータ出力情報.
!
! 初期設定やデフォルト値の設定などを
! 行った後に与えること.
!
! Individual data output information from
! "NAMELIST\##{@mod_name}_history_nml".
!
! Before this argument is given to
! this procedure, initialize and
! configure the defaut settings.
EOF
end
str << <<-EOF
logical, intent(out), optional:: err
! 例外処理用フラグ.
! デフォルトでは, この手続き内でエラーが
! 生じた場合, プログラムは強制終了します.
! 引数 *err* が与えられる場合,
! プログラムは強制終了せず, 代わりに
! *err* に .true. が代入されます.
!
! Exception handling flag.
! By default, when error occur in
! this procedure, the program aborts.
! If this *err* argument is given,
! .true. is substituted to *err* and
! the program does not abort.
EOF
case @kind
when 'calc', 'sample'
str << <<-EOF
!-----------------------------------
! *#{@arg_keyword}* から取り出される設定値
! Setting values fetched from *#{@arg_keyword}*
!!$ real(DP):: CoefAlpha ! $ \\alpha $ . 係数. Coefficient
!!$ real(DP):: DelTime ! $ \\Delta t $ . タイムステップ. Time step
EOF
when 'nmlread'
str << <<-EOF
!!$ namelist /#{@mod_name}_nml/ &
!!$ & CoefAlpha, key00
!!$ ! #{@mod_name} モジュール用
!!$ ! NAMELIST 変数群名.
!!$ !
!!$ ! #{@mod_name}\##{@basename}Create
!!$ ! を使用する際に, オプショナル引数 *nmlfile*
!!$ ! へ NAMELIST ファイル名を指定することで,
!!$ ! そのファイルからこの NAMELIST 変数群を
!!$ ! 読み込みます.
!!$ !
!!$ ! NAMELIST group name for
!!$ ! "#{@mod_name}" module.
!!$ !
!!$ ! If a NAMELIST filename is specified to
!!$ ! an optional argument *nmlfile* when
!!$ ! "#{@mod_name}\##{@basename}Create"
!!$ ! is used, this NAMELIST group is
!!$ ! loaded from the file.
character(STRING):: name
! 変数名.
! 空白の場合には, この他の設定値は
! #{@mod_name} モジュールにおいて
! 出力されるデータ全ての
! デフォルト値となります.
!
! "Data1,Data2" のようにカンマで区切って複数
! の変数を指定することも可能です.
!
! Variable identifier.
! If blank is given, other values are
! used as default values of output data
! in "#{@mod_name}".
!
! Multiple variables can be specified
! as "Data1,Data2" too. Delimiter is comma.
character(STRING):: file
! 出力ファイル名.
! これはデフォルト値としては使用されません.
! *name* に値が設定されている時のみ有効です.
!
! Output file name.
! This is not used as default value.
! This value is valid only when *name* is
! specified.
real:: interval_value
! ヒストリデータの出力間隔の数値.
! 負の値を与えると, 出力を抑止します.
! Numerical value for interval of history data output
! Negative values suppresses output.
character(TOKEN):: interval_unit
! ヒストリデータの出力間隔の単位.
! Unit for interval of history data output
character(TOKEN):: precision
! ヒストリデータの精度.
! Precision of history data
logical:: average
! 出力データの平均化フラグ.
! Flag for average of output data
character(STRING):: fileprefix
! ヒストリデータのファイル名の接頭詞.
! Prefixes of history data filenames
namelist /#{@mod_name}_history_nml/ &
& name, &
& file, &
& interval_value, &
& interval_unit, &
& precision, &
& fileprefix, &
& average
! #{@mod_name} モジュールのヒストリデータ用
! NAMELIST 変数群名.
!
! #{@mod_name}\##{@basename}Create
! を使用する際に, オプショナル引数 *nmlfile*
! へ NAMELIST ファイル名を指定することで,
! そのファイルからこの NAMELIST 変数群を
! 読み込みます.
!
! NAMELIST group name for
! history data of "#{@mod_name}" module.
!
! If a NAMELIST filename is specified to
! an optional argument *nmlfile* when
! "#{@mod_name}\##{@basename}Create"
! is used, this NAMELIST group is
! loaded from the file.
EOF
end
case @kind
when 'create', 'close', 'settime', 'calc'
str << <<-EOF
!-----------------------------------
! ヒストリファイルへのデータ出力設定
! Configure the settings for history data output
character(STRING):: name = ''
! 変数名. Variable identifier
EOF
end
case @kind
when 'create'
str << <<-EOF
character(STRING):: longname = ''
! 変数の記述的名称. Descriptive name of variables
character(STRING), allocatable:: dims(:)
! 座標軸の名称. Name of axes
character(STRING):: units = ''
! 単位. Units
type(GT_HISTORY), pointer:: gthist =>null()
! gt4_history モジュール用構造体.
! Derived type for "gt4_history" module
character(TOKEN):: precision
! ヒストリデータの精度.
! Precision of history data
logical:: average
! 出力データの平均化フラグ.
! Flag for average of output data
type(HASH):: registered_varnames
! このモジュールから出力される変数名のリスト.
!
! List of names of variables output
! from this module.
logical:: hash_end
! HASH オブジェクトの終了フラグ.
!
! End flag of "HASH" object
logical:: allvar_invalid
! 無効な変数名のチェックフラグ.
!
! Check flag of invalid variable names
character(STRING):: names_invalid
! 無効な変数名.
!
! Invalid variable names
character(STRING):: nmlfile_msg
! NAMELIST ファイル名に関するメッセージ.
!
! Messages about NAMELIST file name
EOF
when 'close'
str << <<-EOF
character(STRING):: varnames
! 変数名リスト.
! List of variables
character(TOKEN), pointer:: varnames_array(:) =>null()
! 変数名リスト配列.
! List of variables (array)
integer:: i, vnmax
type(GT_HISTORY), pointer:: gthist =>null()
! gt4_history モジュール用構造体.
! Derived type for "gt4_history" module
EOF
when 'settime'
str << <<-EOF
character(TOKEN):: interval_unit
! ヒストリデータの出力間隔の単位.
! Unit for interval of history data output
character(STRING):: varnames
! 変数名リスト.
! List of variables
character(TOKEN), pointer:: varnames_array(:) =>null()
! 変数名リスト配列.
! List of variables (array)
integer:: i, vnmax
type(GT_HISTORY), pointer:: gthist =>null()
! gt4_history モジュール用構造体.
! Derived type for "gt4_history" module
EOF
when 'calc'
str << <<-EOF
real:: time
! 時刻. Time
type(GT_HISTORY), pointer:: gthist =>null()
! gt4_history モジュール用構造体.
! Derived type for "gt4_history" module
EOF
end
str << <<-EOF
!-----------------------------------
! 作業変数
! Work variables
integer:: stat
character(STRING):: cause_c
EOF
case @kind
when 'putline'
str << <<-EOF
integer:: out_unit
integer:: indent_len
character(STRING):: indent_str
EOF
when 'nmlread'
str << <<-EOF
integer:: unit_nml ! NAMELIST ファイルオープン用装置番号.
! Unit number for NAMELIST file open
integer:: iostat_nml ! NAMELIST 読み込み時の IOSTAT.
! IOSTAT of NAMELIST read
character(TOKEN):: pos_nml
! NAMELIST 読み込み時のファイル位置.
! File position of NAMELIST read
EOF
end
return str.chomp
end
def dc_default_preinit
case @kind
when 'initialized'
return ''
end
case @kind
when 'create'
str = <<-EOF
call BeginSub( subname, version )
EOF
else
str = <<-EOF
call BeginSub( subname )
EOF
end
str << <<-EOF
stat = DC_NOERR
cause_c = ''
EOF
return str.chomp
end
def dc_default_initialize
case @kind
when 'initialized'
return ''
end
case @kind
when 'putline'
str = <<-EOF
!-----------------------------------------------------------------
! 出力先装置番号と字下げの設定
! Configure output unit number and indents
!-----------------------------------------------------------------
EOF
else
str = <<-EOF
!-----------------------------------------------------------------
! 初期設定のチェック
! Check initialization
!-----------------------------------------------------------------
EOF
end
case @kind
when 'create'
str << <<-EOF
if ( #{@arg_keyword} % initialized ) then
stat = #{@alreadyinit_err_code}
cause_c = '#{@arg_type}'
goto 999
end if
!-----------------------------------------------------------------
! 引数の正当性のチェック
! Validate arguments
!-----------------------------------------------------------------
!!$ if (imax < 1) then
!!$ stat = DC_ENEGATIVE
!!$ cause_c = 'imax'
!!$ goto 999
!!$ end if
!!$ if (jmax < 1) then
!!$ stat = DC_ENEGATIVE
!!$ cause_c = 'jmax'
!!$ goto 999
!!$ end if
!!$ if (DelTime < 0.0_DP) then
!!$ stat = DC_ENEGATIVE
!!$ cause_c = 'DelTime'
!!$ goto 999
!!$ end if
EOF
when 'putline'
str << <<-EOF
if ( present(unit) ) then
out_unit = unit
else
out_unit = STDOUT
end if
indent_len = 0
indent_str = ''
if ( present(indent) ) then
if ( len(indent) /= 0 ) then
indent_len = len(indent)
indent_str(1:indent_len) = indent
end if
end if
EOF
when 'nmlread'
else
str << <<-EOF
if ( .not. #{@arg_keyword} % initialized ) then
stat = #{@noinit_err_code}
cause_c = '#{@arg_type}'
goto 999
end if
EOF
end
return str.chomp
end
def dc_default_operate
case @kind
when 'create'
str = <<-EOF
!-----------------------------------------------------------------
! 波数・格子点の設定
! Configure wave number and grid point
!-----------------------------------------------------------------
!!$ #{@arg_keyword} % imax = imax
!!$ #{@arg_keyword} % jmax = jmax
!-----------------------------------------------------------------
! 座標軸の設定
! Configure axes
!-----------------------------------------------------------------
!!$ allocate( #{@arg_keyword} % x_Lon (0:imax-1) )
!!$ #{@arg_keyword} % x_Lon = x_Lon
!!$
!!$ allocate( #{@arg_keyword} % y_Lat (0:jmax-1) )
!!$ #{@arg_keyword} % y_Lat = y_Lat
!-----------------------------------------------------------------
! 時刻管理
! Time control
!-----------------------------------------------------------------
!!$ if ( present(current_time_value) .and. present(current_time_unit) ) then
!!$ call DCDiffTimeCreate( &
!!$ & diff = #{@arg_keyword} % current_time, & ! (out)
!!$ & value = real( current_time_value, DP ), & ! (in)
!!$ & unit = current_time_unit ) ! (in)
!!$ else
!!$ call DCDiffTimeCreate( &
!!$ & diff = #{@arg_keyword} % current_time, & ! (out)
!!$ & value = 0.0_DP, & ! (in)
!!$ & unit = 'sec' ) ! (in)
!!$ end if
!!$
!!$ call DCDiffTimeCreate( &
!!$ & diff = #{@arg_keyword} % delta_time, & ! (out)
!!$ & value = DelTime, & ! (in)
!!$ & unit = 'sec' ) ! (in)
!-----------------------------------------------------------------
! "#{@arg_type}" の設定
! Configure the settings for "#{@arg_type}"
!-----------------------------------------------------------------
!!$ #{@arg_keyword} % CoefAlpha = CoefAlpha
!!$ #{@arg_keyword} % key00 = ''
!-----------------------------------------------------------------
! ヒストリファイルへのデータ出力設定
! Configure the settings for history data output
!-----------------------------------------------------------------
!-------------------------
! デフォルト値
! Default values
call HstNmlInfoCreate( gthstnml = #{@arg_keyword} % gthstnml ) ! (inout)
!-------------------------
! オプショナル引数からの値
! Values from optional arguments
call HstNmlInfoAdd( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (inout)
& name = '', & ! (in)
& interval_value = history_interval_value, & ! (in)
& interval_unit = history_interval_unit, & ! (in)
& precision = history_precision, & ! (in)
& average = .false., & ! (in)
& fileprefix = history_fileprefix ) ! (in)
if ( present(history_varlist) ) then
call HstNmlInfoAdd( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (inout)
& name = history_varlist ) ! (in)
end if
!-----------------------------------------------------------------
! NAMELIST からの値の読み込み
! Load values from NAMELIST
!-----------------------------------------------------------------
if ( present_and_not_empty(nmlfile) ) then
call MessageNotify( 'M', subname, &
& 'Loading NAMELIST file "%c" ...', &
& c1 = trim(nmlfile) )
call NmlRead ( nmlfile = nmlfile, & ! (in)
!!$ & CoefAlpha = #{@arg_keyword} % CoefAlpha, & ! (inout)
!!$ & key00_ = #{@arg_keyword} % key00, & ! (inout)
& gthstnml = #{@arg_keyword} % gthstnml, & ! (inout)
& err = err ) ! (out)
if ( present_and_true(err) ) then
call MessageNotify( 'W', subname, &
& '"%c" can not be read.', &
& c1 = trim(nmlfile) )
stat = DC_ENOFILEREAD
cause_c = nmlfile
goto 999
end if
end if
call HstNmlInfoEndDefine( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (inout)
& err = err ) ! (out)
if ( present_and_true( err ) ) then
stat = USR_ERRNO
goto 999
end if
!-----------------------------------------------------------------
! データ出力の初期設定
! Initialize data output
!-----------------------------------------------------------------
!!$ !-------------------------
!!$ ! x_Data1 の出力設定
!!$ ! Configure the settings for "x_Data1" output
!!$ name = 'Data1'
!!$ longname = 'Sample data (1)'
!!$ units = '1'
!!$ allocate( dims(2) )
!!$ dims = StoA( 'lon', 'time' )
!!$
!!$ ! 出力ファイルの初期設定.
!!$ ! * gthist (gt4_history#GT_HISTORY) が設定される.
!!$ ! Initialize output file.
!!$ ! * "gthist" (gt4_history#GT_HISTORY) is configured.
!!$ call output_init ! これは内部サブルーチン. This is an internal subroutine
!!$
!!$ ! 属性の付加などを行う場合には以下のようにする.
!!$ ! Describe codes as follows in order to add attributes etc.
!!$ if ( associated( gthist ) ) then
!!$ call HistoryAddAttr( &
!!$ & history = gthist, & ! (inout)
!!$ & varname = name, attrname = 'missing_value', & ! (in)
!!$ & value = 9999.0 ) ! (in)
!!$ end if
!!$ deallocate( dims )
!!$
!!$ !-------------------------
!!$ ! y_Data2 の出力設定
!!$ ! Configure the settings for "y_Data2" output
!!$ name = 'Data2'
!!$ longname = 'Sample data (2)'
!!$ units = '1'
!!$ allocate( dims(2) )
!!$ dims = StoA( 'lat', 'time' )
!!$
!!$ ! 出力ファイルの初期設定.
!!$ ! * gthist (gt4_history#GT_HISTORY) が設定される.
!!$ ! Initialize output file.
!!$ ! * "gthist" (gt4_history#GT_HISTORY) is configured.
!!$ call output_init ! これは内部サブルーチン. This is an internal subroutine
!!$ deallocate( dims )
!-----------------------------------------------------------------
! このモジュールから出力される変数名のリストを表示
! Print list of names of variables output from this module
!-----------------------------------------------------------------
call Printf( STDOUT, &
& ' *** MESSAGE *** +---- "%c" module output varnames list -----', &
& c1 = '#{@mod_name}' )
call DCHashRewind( hashv = registered_varnames ) ! (inout)
do
call DCHashNext( hashv = registered_varnames, & ! (inout)
& key = name, value = longname, end = hash_end ) ! (out)
if ( hash_end ) exit
call Printf( STDOUT, &
& ' *** MESSAGE *** | "%c" (%c)', &
& c1 = trim(name), c2 = trim(longname) )
enddo
call DCHashDelete( hashv = registered_varnames ) ! (inout)
call Printf( STDOUT, &
& ' *** MESSAGE *** `----------------------------------------' )
!-----------------------------------------------------------------
! 無効な変数名のチェック
! Check invalid variable names
!-----------------------------------------------------------------
call HstNmlInfoAllNameValid( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (inout)
& invalid = allvar_invalid, names = names_invalid, & ! (out)
& err = err ) ! (out)
if ( allvar_invalid ) then
stat = HST_EBADVARNAME
cause_c = names_invalid
#{@arg_keyword} % initialized = .true.
call #{@basename}Close( #{@arg_keyword}, & ! (inout)
& err = err ) ! (out)
if ( present(nmlfile) ) then
nmlfile_msg = ' or NAMELIST "#{@mod_name}_history_nml" in "'// trim(nmlfile) // '"'
else
nmlfile_msg = ''
end if
call MessageNotify( 'W', subname, &
& 'names "%c" from an optional argument "history_varlist"%c are invalid.', &
& c1 = trim(names_invalid), &
& c2 = trim(nmlfile_msg) )
goto 999
end if
!-----------------------------------------------------------------
! 設定値の正当性のチェック
! Validate setting values
!-----------------------------------------------------------------
!!$ if ( #{@arg_keyword} % CoefAlpha < 0.0_DP ) then
!!$ stat = DC_ENEGATIVE
!!$ cause_c = 'CoefAlpha'
!!$ goto 999
!!$ end if
EOF
when 'calc'
str = <<-EOF
!-----------------------------------------------------------------
! *#{@arg_keyword}* に格納されている設定値の取り出し
! Fetch setting values stored in *#{@arg_keyword}*
!-----------------------------------------------------------------
!!$ CoefAlpha = #{@arg_keyword} % CoefAlpha
!!$ DelTime = EvalSec( #{@arg_keyword} % delta_time )
!-----------------------------------------------------------------
! 時間変化の演算
! Calculate tendency
!-----------------------------------------------------------------
!!$ x_Data1 = ( 1.0_DP - CoefAlpha * DelTime ) * x_Data1
!!$ y_Data2 = ( 1.0_DP - CoefAlpha * DelTime ) * y_Data2
!----------------------------------------------------------------
! ヒストリファイルへのデータ出力
! History data output
!----------------------------------------------------------------
!!$ !-----------------------------------
!!$ ! x_Data1 の出力
!!$ ! Output "x_Data1"
!!$ name = 'Data1'
!!$
!!$ ! 出力のチェック.
!!$ ! * gthist (gt4_history#GT_HISTORY), time (単精度実数型) が設定される.
!!$ ! Check for output.
!!$ ! * "gthist" (gt4_history#GT_HISTORY), time (real) are configured.
!!$ call output_check ! これは内部サブルーチン. This is an internal subroutine
!!$
!!$ ! 出力データを引数 array に渡す.
!!$ ! Give output data to argument "array"
!!$ if ( associated( gthist ) ) then
!!$ call HistoryPut( &
!!$ & history = gthist, & ! (inout)
!!$ & varname = name, array = x_Data1, & ! (in)
!!$ & time = time, quiet = .false., & ! (in)
!!$ & err = err ) ! (out)
!!$ end if
!!$
!!$ !-----------------------------------
!!$ ! y_Data2 の出力
!!$ ! Output "y_Data2"
!!$ name = 'Data2'
!!$
!!$ ! 出力のチェック.
!!$ ! * gthist (gt4_history#GT_HISTORY), time (単精度実数型) が設定される.
!!$ ! Check for output.
!!$ ! * "gthist" (gt4_history#GT_HISTORY), time (real) are configured.
!!$ call output_check ! これは内部サブルーチン. This is an internal subroutine
!!$
!!$ ! 出力データを引数 array に渡す.
!!$ ! Give output data to argument "array"
!!$ if ( associated( gthist ) ) then
!!$ call HistoryPut( &
!!$ & history = gthist, & ! (inout)
!!$ & varname = name, array = y_Data2, & ! (in)
!!$ & time = time, quiet = .false., & ! (in)
!!$ & err = err ) ! (out)
!!$ end if
!-----------------------------------------------------------------
! 時刻の更新
! Update time
!-----------------------------------------------------------------
!!$ #{@arg_keyword} % current_time = &
!!$ & #{@arg_keyword} % current_time + #{@arg_keyword} % delta_time
EOF
when 'close'
str = <<-EOF
!-----------------------------------------------------------------
! "#{@arg_type}" の設定の消去
! Clear the settings for "#{@arg_type}"
!-----------------------------------------------------------------
!!$ deallocate( #{@arg_keyword} % x_Lon )
!!$ deallocate( #{@arg_keyword} % y_Lat )
!-----------------------------------------------------------------
! ヒストリファイルへのデータ出力の終了処理
! Terminate the settings for history data output
!-----------------------------------------------------------------
varnames = HstNmlInfoNames( #{@arg_keyword} % gthstnml )
call Split( str = varnames, sep = ',', & ! (in)
& carray = varnames_array ) ! (out)
vnmax = size( varnames_array )
do i = 1, vnmax
name = varnames_array(i)
if ( trim( name ) == '' ) exit
nullify( gthist )
call HstNmlInfoAssocGtHist( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (in)
& name = name, & ! (in)
& history = gthist, & ! (out)
& err = err ) ! (out)
if ( HistoryInitialized( gthist ) ) then
call HistoryClose( history = gthist, & ! (inout)
& err = err ) ! (out)
end if
end do
!-----------------------------------------------------------------
! ヒストリファイルへのデータ出力設定の割付解除
! Deallocate the settings for history data output
!-----------------------------------------------------------------
call HstNmlInfoClose( &
& #{@arg_keyword} % gthstnml, & ! (inout)
& err = err ) ! (out)
EOF
when 'putline'
str = <<-EOF
!-----------------------------------------------------------------
! "#{@arg_type}" の設定の印字
! Print the settings for "#{@arg_type}"
!-----------------------------------------------------------------
if ( #{@arg_keyword} % initialized ) then
call Printf( unit = out_unit, & ! (in)
& fmt = indent_str(1:indent_len) // &
& '#<#{@arg_type}:: @initialized=%y', & ! (in)
& l = (/ #{@arg_keyword} % initialized /) ) ! (in)
!!$ call Printf( unit = out_unit, & ! (in)
!!$ & fmt = indent_str(1:indent_len) // & ! (in)
!!$ & ' @imax=%d @jmax=%d', & ! (in)
!!$ & i = (/ #{@arg_keyword} % imax, #{@arg_keyword} % jmax /) ) ! (in)
!!$
!!$ call Printf( unit = out_unit, & ! (in)
!!$ & fmt = indent_str(1:indent_len) // &
!!$ & ' @current_time=%f [sec] @delta_time=%f [sec]', & ! (in)
!!$ & d = (/ EvalSec( #{@arg_keyword} % current_time ), &
!!$ & EvalSec( #{@arg_keyword} % delta_time ) /) ) ! (in)
!!$
!!$ call Printf( unit = out_unit, & ! (in)
!!$ & fmt = indent_str(1:indent_len) // &
!!$ & ' @CoefAlpha=%f', & ! (in)
!!$ & d = (/#{@arg_keyword} % CoefAlpha/) ) ! (in)
!!$
!!$ call Printf( unit = out_unit, & ! (in)
!!$ & fmt = indent_str(1:indent_len) // &
!!$ & ' @key00=%c', & ! (in)
!!$ & c1 = trim( #{@arg_keyword} % key00 ) ) ! (in)
!!$
!!$ call PutLine( array = #{@arg_keyword} % x_Lon, & ! (in)
!!$ & unit = out_unit, & ! (in)
!!$ & lbounds = lbound(#{@arg_keyword} % x_Lon), & ! (in)
!!$ & ubounds = ubound(#{@arg_keyword} % x_Lon), & ! (in)
!!$ & indent = indent_str(1:indent_len) // &
!!$ & ' @x_Lon=' ) ! (in)
!!$
!!$ call PutLine( array = #{@arg_keyword} % y_Lat, & ! (in)
!!$ & unit = out_unit, & ! (in)
!!$ & lbounds = lbound(#{@arg_keyword} % y_Lat), & ! (in)
!!$ & ubounds = ubound(#{@arg_keyword} % y_Lat), & ! (in)
!!$ & indent = indent_str(1:indent_len) // &
!!$ & ' @y_Lat=' ) ! (in)
!!$
call Printf( unit = out_unit, & ! (in)
& fmt = indent_str(1:indent_len) // &
& ' @gthstnml=' ) ! (in)
call HstNmlInfoPutLine( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (in)
& unit = out_unit, & ! (in)
& indent = indent_str(1:indent_len) // ' ' ) ! (in)
call Printf( unit = out_unit, & ! (in)
& fmt = indent_str(1:indent_len) // '>' ) ! (in)
else
call Printf( unit = out_unit, & ! (in)
& fmt = indent_str(1:indent_len) // & ! (in)
& '#<#{@arg_type}:: @initialized=%y>', & ! (in)
& l = (/#{@arg_keyword} % initialized/) ) ! (in)
end if
EOF
when 'initialized'
str = <<-EOF
result = #{@arg_keyword} % initialized
EOF
when 'settime'
str = <<-EOF
!-----------------------------------------------------------------
! 時刻設定
! Configure time
!-----------------------------------------------------------------
call DCDiffTimeCreate( &
& diff = #{@arg_keyword} % current_time, & ! (out)
& value = real( current_time_value, DP ), & ! (in)
& unit = current_time_unit ) ! (in)
!-----------------------------------------------------------------
! ヒストリファイルへのデータの時刻設定
! Configure the time of history data
!-----------------------------------------------------------------
varnames = HstNmlInfoNames( #{@arg_keyword} % gthstnml )
call Split( str = varnames, sep = ',', & ! (in)
& carray = varnames_array ) ! (out)
vnmax = size( varnames_array )
do i = 1, vnmax
name = varnames_array(i)
if ( trim( name ) == '' ) exit
call HstNmlInfoOutputStepDisable( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (inout)
& name = name, & ! (in)
& err = err ) ! (out)
nullify( gthist )
call HstNmlInfoAssocGtHist( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (in)
& name = name, & ! (in)
& history = gthist, & ! (out)
& err = err ) ! (out)
if ( HistoryInitialized( gthist ) ) then
call HstNmlInfoInquire( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (in)
& name = name, & ! (in)
& interval_unit = interval_unit ) ! (out)
call HistorySetTime( &
& history = gthist, & ! (inout)
& time = &
& real( EvalbyUnit( #{@arg_keyword} % current_time, &
& interval_unit) ) ) ! (in)
end if
end do
EOF
when 'nmlread'
str = <<-EOF
!-----------------------------------------------------------------
! 文字型引数を NAMELIST 変数群へ代入
! Substitute character arguments to NAMELIST group
!-----------------------------------------------------------------
!!$ key00 = key00_
!----------------------------------------------------------------
! NAMELIST ファイルのオープン
! Open NAMELIST file
!----------------------------------------------------------------
call FileOpen( unit = unit_nml, & ! (out)
& file = nmlfile, mode = 'r', & ! (in)
& err = err ) ! (out)
if ( present_and_true(err) ) then
stat = DC_ENOFILEREAD
cause_c = nmlfile
goto 999
end if
!-----------------------------------------------------------------
! NAMELIST 変数群の取得
! Get NAMELIST group
!-----------------------------------------------------------------
!-------------------------
! 係数などの取得
! Get coefficients etc.
!!$ rewind( unit_nml )
!!$ read( unit = unit_nml, & ! (in)
!!$ & nml = #{@mod_name}_nml, & ! (out)
!!$ & iostat = iostat_nml ) ! (out)
!!$ if ( iostat_nml == 0 ) then
!!$ call MessageNotify( 'M', subname, &
!!$ & 'NAMELIST group "%c" is loaded from "%c".', &
!!$ & c1 = '#{@mod_name}_nml', c2 = trim(nmlfile) )
!!$ write(STDOUT, nml = #{@mod_name}_nml)
!!$ else
!!$ call MessageNotify( 'W', subname, &
!!$ & 'NAMELIST group "%c" is not found in "%c" (iostat=%d).', &
!!$ & c1 = '#{@mod_name}_nml', c2 = trim(nmlfile), &
!!$ & i = (/iostat_nml/) )
!!$ end if
!!$
!-------------------------
! 出力データの個別情報の取得
! Get individual information of output data
rewind( unit_nml )
iostat_nml = 0
pos_nml = ''
do while ( trim(pos_nml) /= 'APPEND' .and. iostat_nml == 0 )
name = ''
file = ''
call HstNmlInfoInquire( &
& gthstnml = gthstnml, & ! (in)
& interval_value = interval_value, & ! (out)
& interval_unit = interval_unit, & ! (out)
& precision = precision, & ! (out)
& average = average, & ! (out)
& fileprefix = fileprefix ) ! (out)
read( unit = unit_nml, & ! (in)
& nml = #{@mod_name}_history_nml, & ! (out)
& iostat = iostat_nml ) ! (out)
inquire( unit = unit_nml, & ! (in)
& position = pos_nml ) ! (out)
if ( iostat_nml == 0 ) then
call MessageNotify( 'M', subname, &
& 'NAMELIST group "%c" is loaded from "%c".', &
& c1='#{@mod_name}_history_nml', c2=trim(nmlfile) )
write(STDOUT, nml = #{@mod_name}_history_nml)
call HstNmlInfoAdd( &
& gthstnml = gthstnml, & ! (in)
& name = name, & ! (in)
& file = file, & ! (in)
& interval_value = interval_value, & ! (in)
& interval_unit = interval_unit, & ! (in)
& precision = precision, & ! (in)
& average = average, & ! (in)
& fileprefix = fileprefix ) ! (in)
else
call MessageNotify( 'W', subname, &
& 'NAMELIST group "%c" is not found in "%c" any more (iostat=%d).', &
& c1='#{@mod_name}_history_nml', c2=trim(nmlfile), &
& i = (/iostat_nml/) )
end if
end do
close( unit_nml )
!-----------------------------------------------------------------
! NAMELIST 変数群を文字型引数へ代入
! Substitute NAMELIST group to character arguments
!-----------------------------------------------------------------
!!$ key00_ = key00
EOF
else
str = <<-EOF
!-----------------------------------------------------------------
! *#{@arg_keyword}* に格納されている設定値の取り出し
! Fetch setting values stored in *#{@arg_keyword}*
!-----------------------------------------------------------------
!!$ CoefAlpha = #{@arg_keyword} % CoefAlpha
!!$ DelTime = EvalSec( #{@arg_keyword} % delta_time )
EOF
end
return str.chomp
end
def dc_default_terminate
case @kind
when 'initialized'
return ""
end
str = <<-EOF
!-----------------------------------------------------------------
! 終了処理, 例外処理
! Termination and Exception handling
!-----------------------------------------------------------------
EOF
case @kind
when 'create'
str << <<-EOF
#{@arg_keyword} % initialized = .true.
EOF
when 'close'
str << <<-EOF
#{@arg_keyword} % initialized = .false.
EOF
end
str << <<-EOF
999 continue
call StoreError( stat, subname, err, cause_c )
call EndSub( subname )
EOF
return str.chomp
end
def dc_default_internal_procedures
str = ''
case @kind
when 'create'
str << <<-EOF
contains
subroutine output_init
!
! 変数 *name* に関して出力ファイルの初期設定を行います.
! 出力ファイル名や出力間隔などの情報は #{@arg_keyword} % gthstnml
! から取り出されます.
!
! 変数 *name* に関して出力が行われる場合には,
! *gthist* に出力先ファイルの gt4_history#GT_HISTORY
! 型変数を結合させます. そうでない場合は, *gthist* を空状態にします.
!
! また, 出力データの精度を precision に,
! 出力データ平均化の可否を average に設定します.
!
! 標準出力に表示される変数リスト *registered_varnames* に
! *name*, *longname*, *dims*, *units* が登録されます.
!
! An output file is initialized for a variable *name*.
! Information such as the output filename and output intervals
! is taken out of "#{@arg_keyword} % gthstnml".
!
! When output is done for the variable *name*, *gthist* is
! associated with the "gt4_history#GT_HISTORY" variable of
! the output file. Otherwise, *gthist* is nullified.
!
! Moreover, the accuracy of output data is set to *precision*, and
! right or wrong of averaging the output data is set to *average*.
!
! *name*, *longname*, *dims*, *units* are registered to
! a list of variables *registered_varnames* that is printed to
! standard output.
!
use dc_date, only: DCDiffTimeCreate, EvalSec, EvalByUnit
use gt4_history_nmlinfo, only: GTHST_NMLINFO, &
& HstNmlInfoInitialized, HstNmlInfoInquire, &
& HstNmlInfoOutputValid, HstNmlInfoAssocGtHist, HstNmlInfoPutLine, &
& HstNmlInfoSetValidName
use gt4_history, only: GT_HISTORY, &
& HistoryCreate, HistoryAddVariable, HistoryPut, &
& HistoryAddAttr, HistoryInitialized
!-----------------------------------
! 作業変数
! Work variables
character(STRING):: file
! ヒストリデータのファイル名.
! History data filenames
character(STRING):: dims_str
! 座標軸のリスト.
! List of axes
real:: interval_value
! ヒストリデータの出力間隔の数値.
! Numerical value for interval of history data output
character(TOKEN):: interval_unit
! ヒストリデータの出力間隔の単位.
! Unit for interval of history data output
real(DP), parameter:: PI = 3.1415926535897930_DP
! $ \\pi $ . 円周率. Circular constant
continue
!-----------------------------------------------------------------
! 標準出力に表示される変数の登録
! Register a variable name for print to standard output
!-----------------------------------------------------------------
if ( allocated(dims) ) then
dims_str = JoinChar( dims, ',' )
else
dims_str = ''
end if
call DCHashPut( hashv = registered_varnames, & ! (inout)
& key = name, & ! (in)
& value = trim( longname ) // ' [' // &
& trim( units ) // '] {' // &
& trim( dims_str ) // '}' ) ! (in)
!-----------------------------------------------------------------
! 変数の初期化
! Initialize variable
!-----------------------------------------------------------------
nullify( gthist )
precision = 'float'
average = .false.
!-----------------------------------------------------------------
! 変数名の有効性を設定
! Set validation of the variable name
!-----------------------------------------------------------------
call HstNmlInfoSetValidName( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (in)
& name = name ) ! (in)
!-----------------------------------------------------------------
! 出力が有効かどうかを確認する
! Confirm whether the output is effective
!-----------------------------------------------------------------
if ( .not. HstNmlInfoOutputValid( #{@arg_keyword} % gthstnml, name ) ) then
return
end if
!-----------------------------------------------------------------
! GT_HISTORY 変数の取得
! Get "GT_HISTORY" variable
!-----------------------------------------------------------------
call HstNmlInfoAssocGtHist( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (in)
& name = name, & ! (in)
& history = gthist, & ! (out)
& err = err ) ! (out)
if ( present_and_true( err ) ) return
call HstNmlInfoInquire( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (in)
& name = name, & ! (in)
& precision = precision, & ! (out)
& average = average, & ! (out)
& err = err ) ! (out)
if ( present_and_true( err ) ) return
!-----------------------------------------------------------------
! GT_HISTORY 変数の初期設定の確認
! Check initialization of "GT_HISTORY" variable
!-----------------------------------------------------------------
if ( HistoryInitialized( gthist ) ) then
!---------------------------------------------------------------
! HistoryAddVariable による変数作成
! A variable is created by "HistoryAddVariable"
!---------------------------------------------------------------
call HistoryAddVariable( &
& history = gthist, & ! (inout)
& varname = name, dims = dims, & ! (in)
& longname = longname, units = units, & ! (in)
& xtype = precision, average = average ) ! (in)
return
end if
!-----------------------------------------------------------------
! HistoryCreate のための設定値の取得
! Get the settings for "HistoryCreate"
!-----------------------------------------------------------------
call HstNmlInfoInquire( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (in)
& name = name, & ! (in)
& file = file, & ! (out)
& interval_unit = interval_unit, & ! (out)
& interval_value = interval_value, & ! (out)
& err = err ) ! (out)
if ( present_and_true( err ) ) return
!-----------------------------------------------------------------
! HistoryCreate によるファイル作成
! Files are created by "HistoryCreate"
!-----------------------------------------------------------------
!!$ call HistoryCreate( &
!!$ & history = gthist, & ! (out)
!!$ & file = file, & ! (in)
!!$ & title = 'Sample program of dcmodel programming guideline', & ! (in)
!!$ & source = 'dcmodel project : ' // trim(version), & ! (in)
!!$ & institution = 'GFD Dennou Club', & ! (in)
!!$ & dims = StoA( 'lon', 'lat', 'time' ), & ! (in)
!!$ & dimsizes = (/ #{@arg_keyword} % imax, #{@arg_keyword} % jmax, 0 /), & ! (in)
!!$ & longnames = StoA( 'longitude', 'latitude', 'time' ), & ! (in)
!!$ & units = StoA( 'degree_east', 'degree_north', &
!!$ & interval_unit ), & ! (in)
!!$ & origin = real( EvalbyUnit( #{@arg_keyword} % current_time, &
!!$ & interval_unit) ), & ! (in)
!!$ & interval = interval_value, & ! (in)
!!$ & err = err ) ! (out)
!!$ if ( present_and_true( err ) ) then
!!$ nullify( gthist )
!!$ return
!!$ end if
!!$
!!$ call HistoryAddAttr( &
!!$ & history = gthist, & ! (inout)
!!$ & varname = 'lon', attrname = 'standard_name', & ! (in)
!!$ & value = 'longitude' ) ! (in)
!!$ call HistoryAddAttr( &
!!$ & history = gthist, & ! (inout)
!!$ & varname = 'lat', attrname = 'standard_name', & ! (in)
!!$ & value = 'latitude' ) ! (in)
!!$ call HistoryAddAttr( &
!!$ & history = gthist, & ! (inout)
!!$ & varname = 'time', attrname = 'standard_name', & ! (in)
!!$ & value = 'time' ) ! (in)
!!$
!!$ call HistoryPut( &
!!$ & history = gthist, & ! (inout)
!!$ & varname = 'lon', & ! (in)
!!$ & array = #{@arg_keyword} % x_Lon / PI * 180.0_DP ) ! (in)
!!$ call HistoryPut( &
!!$ & history = gthist, & ! (inout)
!!$ & varname = 'lat', & ! (in)
!!$ & array = #{@arg_keyword} % y_Lat / PI * 180.0_DP ) ! (in)
!-----------------------------------------------------------------
! HistoryAddVariable による変数作成
! A variable is created by "HistoryAddVariable"
!-----------------------------------------------------------------
if ( HistoryInitialized( gthist ) ) then
call HistoryAddVariable( &
& history = gthist, & ! (inout)
& varname = name, dims = dims, & ! (in)
& longname = longname, units = units, & ! (in)
& xtype = precision, average = average ) ! (in)
else
nullify( gthist )
end if
end subroutine output_init
EOF
when 'calc'
str << <<-EOF
contains
subroutine output_check
!
! 変数 *name* を出力するかどうかをチェックします.
! 出力に関する情報は dcm_sam_cod % gthstnml から取り出されます.
!
! 変数 *name* に関して出力するよう設定されている場合には,
! *gthist* に出力先ファイルの gt4_history#GT_HISTORY
! 型変数を結合させます. そうでない場合は, *gthist* を空状態にします.
!
! また, 現在時刻を *time* に設定します.
!
! Check whether to output variable *name*.
! Information about output is taken out of "dcm_sam_cod % gthstnml".
!
! When output is done for the variable *name*, *gthist* is
! associated with "gt4_history#GT_HISTORY" variable of
! the output file. Otherwise, *gthist* is nullified.
!
! Moreover, current time is set to *time*.
!
character(TOKEN):: interval_unit
! ヒストリデータの出力間隔の単位.
! Unit for interval of history data output
continue
nullify( gthist )
time = 0.0
if ( HstNmlInfoOutputValid( #{@arg_keyword} % gthstnml, name ) ) then
call HstNmlInfoInquire( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (in)
& name = name, & ! (in)
& interval_unit = interval_unit ) ! (out)
time = real( EvalbyUnit( #{@arg_keyword} % current_time, interval_unit ) )
if ( present_and_true( historyput_flag ) ) time = 0.0
call HstNmlInfoAssocGtHist( &
& gthstnml = #{@arg_keyword} % gthstnml, & ! (in)
& name = name, & ! (in)
& history = gthist, err = err ) ! (out)
if ( present_and_true( err ) ) then
nullify( gthist )
return
end if
if ( .not. HistoryInitialized( gthist ) ) nullify( gthist )
end if
end subroutine output_check
EOF
end
return str.chomp
end
end
#
# {dcmodel プログラミングガイドライン}[http://www.gfd-dennou.org/library/dcmodel/coding-rules/dcmodel-coding-rules.htm]に基づく
# Fortran 90/95 ソースコード (モジュール) のテストプログラムの雛形となる
# コードを生成するためのクラス.
#
class DCModelF90SampleTestMaker
include F90CodeChecker
attr_accessor :lang_ja
def initialize(quiet=nil)
@mod_name = 'dcmodel_sample_code'
@program_name = @mod_name + '_test'
autoset_names
@quiet = quiet
@author = 'unknown'
@copyright = 'GFD Dennou Club'
@lang_ja = true
end
#
# ファイル名としてふさわしい名前を返す.
#
def filename
return @program_name + '.f90'
end
def set_modname(modname)
valid_f90entityname?(modname, true)
@mod_name = modname.to_s
@program_name = @mod_name + '_test'
end
def set_programname(programname)
valid_f90entityname?(programname, true)
@program_name = programname.to_s
end
def set_basename(basename)
valid_f90entityname?(basename, true)
@mod_basename = basename.to_s
end
def set_arg_type(arg_type)
valid_f90entityname?(arg_type, true)
@mod_arg_type = arg_type.to_s
end
def set_arg_keyword(arg_keyword)
valid_f90entityname?(arg_keyword, true)
@mod_arg_keyword = arg_keyword.to_s
end
def set_author(author)
@author = author
end
def set_copyright(copyright)
@copyright = copyright
end
#
# @mod_name を元に, 自動的に手続きの名前のベースネームや
# 構造体名, 個々の手続き用の引数キーワード名を作成する.
# @mod_name はいくつかの単語 (小文字) をアンダーバーで繋いだ
# 文字列であることが仮定されている.
#
def autoset_names
return false unless @mod_name =~ /.+\_.+/
@mod_basename = ''
@mod_arg_type = ''
@mod_arg_keyword = ''
@mod_name.split('_').each{ |part|
@mod_basename << part.sub(/^./){|c| c.tr("a-z","A-Z")}
[part.length, 3].min.times{|i|
@mod_arg_type << part[i].chr.tr("a-z","A-Z")
@mod_arg_keyword << part[i].chr.tr("A-Z","a-z")
}
@mod_arg_keyword << '_'
}
@mod_arg_keyword.sub!(/\_+$/, '')
return true
end
#
# このメソッドを呼び出すと, コマンドライン上で
# インタラクティブに設定が行われる.
#
def interactive_setup
@mod_name = f90entityname_from_stdin(@mod_name, 'Module name')
autoset_names
@mod_basename = f90entityname_from_stdin(@mod_basename, 'basename')
@mod_arg_type = f90entityname_from_stdin(@mod_arg_type, 'arg_type')
@mod_arg_keyword = f90entityname_from_stdin(@mod_arg_keyword, 'arg_keyword')
print " Input Your name [#{@author}]: "
author = STDIN.gets.chomp
@author = author unless author == ''
print " Input Copyright [#{@copyright}]: "
copyright = STDIN.gets.chomp
@copyright = copyright unless copyright == ''
end
def to_s
str = ''
str << <<-EOF
!= #{@mod_name} モジュールのテストプログラム
!
!= Test program for "#{@mod_name}"
!
! Authors:: #{@author}
! Version:: $#{}I#{}d: $
! Tag Name:: $#{}N#{}ame: $
! Copyright:: Copyright (C) #{@copyright}, #{Time.now.strftime("%Y")}. All rights reserved.
! License::
!
! Note that Japanese and English are described in parallel.
!
! #{@mod_name} モジュールの動作テストを行うためのプログラムです.
! このプログラムがコンパイルできること, および実行時に
! プログラムが正常終了することを確認してください.
!
! This program checks the operation of "#{@mod_name}" module.
! Confirm compilation and execution of this program.
!
program #{@program_name}
use #{@mod_name}, only: #{@mod_arg_type}, #{@mod_basename}Create, &
& #{@mod_basename}Calculation, #{@mod_basename}Close, &
& #{@mod_basename}PutLine, #{@mod_basename}Initialized, &
& #{@mod_basename}SetTime
use dc_test, only: AssertEqual, AssertGreaterThan, AssertLessThan
use dc_types, only: DP, STRING
use dc_string, only: StoA, PutLine
use dc_args, only: ARGS, DCArgsOpen, DCArgsHelpMsg, DCArgsOption, &
& DCArgsDebug, DCArgsHelp, DCArgsStrict, DCArgsClose
implicit none
!-------------------------------------------------------------------
! 実験の表題, モデルの名称, 所属機関名
! Title of a experiment, name of model, sub-organ
!-------------------------------------------------------------------
character(*), parameter:: title = &
& '#{@program_name} $Name: dcpam4-20080626 $ :: ' // &
& 'Test program of "#{@mod_name}" module'
character(*), parameter:: source = &
& 'dcmodel project: hierarchical numerical models ' // &
& '(See http://www.gfd-dennou.org/library/dcmodel)'
character(*), parameter:: institution = &
& 'GFD Dennou Club (See http://www.gfd-dennou.org)'
!-------------------------------------------------------------------
! 格子点数・最大全波数
! Grid points and maximum truncated wavenumber
!-------------------------------------------------------------------
!!$ integer, parameter:: imax = 8
!!$ ! 経度格子点数.
!!$ ! Number of grid points in longitude
!!$ integer, parameter:: jmax = 4
!!$ ! 緯度格子点数.
!!$ ! Number of grid points in latitude
!-------------------------------------------------------------------
! 軸データ
! Axes data
!-------------------------------------------------------------------
!!$ real(DP):: x_Lon (0:imax-1)
!!$ ! 経度. Longitude
!!$ real(DP):: y_Lat (0:jmax-1)
!!$ ! 緯度. Latitude
!-------------------------------------------------------------------
! 物理量
! Physical values
!-------------------------------------------------------------------
!!$ real(DP):: x_Data1 (0:imax-1)
!!$ ! データ 1. Data 1
!!$ real(DP):: y_Data2 (0:jmax-1)
!!$ ! データ 2. Data 2
!-------------------------------------------------------------------
! 定数
! Constants
!-------------------------------------------------------------------
!!$ real(DP), parameter:: PI = 3.1415926535897930_DP
!!$ ! $ \\pi $ . 円周率. Circular constant
!-------------------------------------------------------------------
! 作業変数
! Work variables
!-------------------------------------------------------------------
!!$ integer:: i, j ! DO ループ用作業変数
!!$ ! Work variables for DO loop
type(ARGS):: arg ! コマンドライン引数.
! Command line options
logical:: OPT_namelist ! -N, --namelist オプションの有無.
! Existence of '-N', '--namelist' option
character(STRING):: VAL_namelist
! -N, --namelist オプションの値.
! Value of '-N', '--namelist' option
type(#{@mod_arg_type}):: #{@mod_arg_keyword}00, #{@mod_arg_keyword}01
!!$ type(#{@mod_arg_type}):: #{@mod_arg_keyword}02, #{@mod_arg_keyword}03
logical:: err
character(*), parameter:: subname = '#{@program_name}'
continue
!-------------------------------------------------------------------
! コマンドライン引数の処理
! Command line options handling
!-------------------------------------------------------------------
call cmdline_optparse ! これは内部サブルーチン. This is an internal subroutine
!-------------------------------------------------------------------
! 軸データの設定
! Configure axes data
!-------------------------------------------------------------------
!!$ x_Lon = (/ 0.0, 45.0, 90.0, 135.0, &
!!$ & 180.0, 225.0, 270.0, 315.0 /) * PI / 180.0_DP
!!$ y_Lat = (/ -59.4444, -19.8757, 19.8757, 59.4444 /) * PI / 180.0_DP
!-------------------------------------------------------------------
! 基本の初期設定, 終了処理テスト
! Basic initialization and termination test
!-------------------------------------------------------------------
call #{@mod_basename}Create( &
& #{@mod_arg_keyword} = #{@mod_arg_keyword}00 & ! (out)
!!$ & , imax = imax, jmax = jmax, & ! (in)
!!$ & x_Lon = x_Lon, y_Lat = y_Lat, & ! (in)
!!$ & CoefAlpha = 0.0001_DP, DelTime = 0.5_DP & ! (in)
& )
call AssertEqual( 'basic initialization test 1', &
& answer = .true., check = #{@mod_basename}Initialized(#{@mod_arg_keyword}00) )
call #{@mod_basename}PutLine( #{@mod_arg_keyword} = #{@mod_arg_keyword}00 ) ! (in)
call #{@mod_basename}Close( #{@mod_arg_keyword} = #{@mod_arg_keyword}00 ) ! (inout)
call AssertEqual( 'basic termination test 1', &
& answer = .false., check = #{@mod_basename}Initialized(#{@mod_arg_keyword}00) )
call #{@mod_basename}PutLine( #{@mod_arg_keyword} = #{@mod_arg_keyword}00 ) ! (in)
!-------------------------------------------------------------------
! 重複初期設定に関するエラー処理のテスト
! Error handling related to duplicated initialization test
!-------------------------------------------------------------------
call #{@mod_basename}Create( &
& #{@mod_arg_keyword} = #{@mod_arg_keyword}00 & ! (inout)
!!$ & , imax = imax, jmax = jmax, & ! (in)
!!$ & x_Lon = x_Lon, y_Lat = y_Lat, & ! (in)
!!$ & CoefAlpha = 0.0001_DP, DelTime = 0.5_DP & ! (in)
& )
call #{@mod_basename}Create( &
& #{@mod_arg_keyword} = #{@mod_arg_keyword}00, & ! (inout)
!!$ & imax = imax, jmax = jmax, & ! (in)
!!$ & x_Lon = x_Lon, y_Lat = y_Lat, & ! (in)
!!$ & CoefAlpha = 0.0001_DP, DelTime = 0.5_DP, & ! (in)
& err = err ) ! (out)
call AssertEqual( 'error handling related to duplicated initialization test 1', &
& answer = .true., check = err )
call #{@mod_basename}PutLine( #{@mod_arg_keyword} = #{@mod_arg_keyword}00 ) ! (in)
call #{@mod_basename}Close( #{@mod_arg_keyword} = #{@mod_arg_keyword}00 ) ! (inout)
!-------------------------------------------------------------------
! 終了処理に関するエラー処理のテスト
! Error handling related to termination test
!-------------------------------------------------------------------
call #{@mod_basename}Close( &
& #{@mod_arg_keyword} = #{@mod_arg_keyword}00, & ! (inout)
& err = err ) ! (out)
call AssertEqual( 'error handling related to termination test 1', &
& answer = .true., check = err )
!-------------------------------------------------------------------
! NAMELIST ファイルの読み込みテスト
! NAMELIST file loading test
!-------------------------------------------------------------------
call #{@mod_basename}Create( &
& #{@mod_arg_keyword} = #{@mod_arg_keyword}01, & ! (out)
!!$ & imax = imax, jmax = jmax, & ! (in)
!!$ & x_Lon = x_Lon, y_Lat = y_Lat, & ! (in)
!!$ & CoefAlpha = - 0.0001_DP, DelTime = 0.5_DP, & ! (in)
& nmlfile = VAL_namelist ) ! (in)
call AssertEqual( 'NAMELIST file loading test 1', &
& answer = .true., check = #{@mod_basename}Initialized(#{@mod_arg_keyword}01) )
call #{@mod_basename}PutLine( #{@mod_arg_keyword} = #{@mod_arg_keyword}01 ) ! (in)
call #{@mod_basename}Close( #{@mod_arg_keyword} = #{@mod_arg_keyword}01 ) ! (inout)
!-------------------------------------------------------------------
! 無効な値に関するエラー処理のテスト
! Error handling related to invalid values test
!-------------------------------------------------------------------
!!$ call #{@mod_basename}Create( &
!!$ & #{@mod_arg_keyword} = #{@mod_arg_keyword}02, & ! (out)
!!$ & imax = imax, jmax = jmax, & ! (in)
!!$ & x_Lon = x_Lon, y_Lat = y_Lat, & ! (in)
!!$ & CoefAlpha = - 0.0001_DP, DelTime = 0.5_DP, & ! (in)
!!$ & err = err ) ! (out)
!!$ call AssertEqual( 'error handling related to invalid values test 1', &
!!$ & answer = .true., check = err )
!!$ call #{@mod_basename}Create( &
!!$ & #{@mod_arg_keyword} = #{@mod_arg_keyword}02, & ! (inout)
!!$ & imax = imax, jmax = jmax, & ! (in)
!!$ & x_Lon = x_Lon, y_Lat = y_Lat, & ! (in)
!!$ & CoefAlpha = 0.0001_DP, DelTime = - 0.5_DP, & ! (in)
!!$ & err = err ) ! (out)
!!$ call AssertEqual( 'error handling related to invalid values test 2', &
!!$ & answer = .true., check = err )
!-------------------------------------------------------------------
! ヒストリデータ出力テスト
! History data output test
!-------------------------------------------------------------------
!!$ call #{@mod_basename}Create( &
!!$ & #{@mod_arg_keyword} = #{@mod_arg_keyword}03, & ! (out)
!!$ & imax = imax, jmax = jmax, & ! (in)
!!$ & x_Lon = x_Lon, y_Lat = y_Lat, & ! (in)
!!$ & CoefAlpha = 0.01_DP, DelTime = 0.5_DP, & ! (in)
!!$ & current_time_value = 0.0, & ! (in)
!!$ & current_time_unit = 'sec', & ! (in)
!!$ & history_varlist = 'Data2', & ! (in)
!!$ & history_interval_value = 2.0, & ! (in)
!!$ & history_interval_unit = 'sec', & ! (in)
!!$ & history_precision = 'float', & ! (in)
!!$ & history_fileprefix = 'AP_' ) ! (in)
!!$ call #{@mod_basename}PutLine( #{@mod_arg_keyword} = #{@mod_arg_keyword}03 ) ! (in)
!!$
!!$ do i = 0, imax-1
!!$ x_Data1(i) = i * 1.0_DP
!!$ end do
!!$ do j = 0, jmax-1
!!$ y_Data2(j) = j * 1.1_DP
!!$ end do
!!$
!!$ do i = 1, 12
!!$ call #{@mod_basename}Calculation( &
!!$ & #{@mod_arg_keyword} = #{@mod_arg_keyword}03, & ! (inout)
!!$ & x_Data1 = x_Data1, y_Data2 = y_Data2 ) ! (inout)
!!$ end do
!!$
!!$ call #{@mod_basename}SetTime( &
!!$ & #{@mod_arg_keyword} = #{@mod_arg_keyword}03, & ! (inout)
!!$ & current_time_value = 1.0, current_time_unit = 'minute' ) ! (in)
!!$
!!$ call #{@mod_basename}Calculation( &
!!$ & #{@mod_arg_keyword} = #{@mod_arg_keyword}03, & ! (inout)
!!$ & x_Data1 = x_Data1, y_Data2 = y_Data2, & ! (inout)
!!$ & historyput_flag = .true. ) ! (in)
!!$
!!$ call #{@mod_basename}Close( #{@mod_arg_keyword} = #{@mod_arg_keyword}03 ) ! (inout)
contains
subroutine cmdline_optparse
!
! コマンドライン引数の処理を行います
!
! Handle command line options
!
call DCArgsOpen( arg = arg ) ! (out)
call DCArgsHelpMsg( arg = arg, & ! (inout)
& category = 'Title', msg = title ) ! (in)
call DCArgsHelpMsg( arg = arg, & ! (inout)
& category = 'Usage', & ! (in)
& msg = './' // trim(subname) // &
& ' [Options]' ) ! (in)
call DCArgsHelpMsg( arg = arg, & ! (inout)
& category = 'Source', msg = source ) ! (in)
call DCArgsHelpMsg( arg = arg, & ! (inout)
& category = 'Institution', & ! (in)
& msg = institution ) ! (in)
call DCArgsOption( arg = arg, & ! (inout)
& options = StoA('-N', '--namelist'), & ! (in)
& flag = OPT_namelist, & ! (out)
& value = VAL_namelist, & ! (out)
& help = "Namelist filename") ! (in)
call DCArgsDebug( arg = arg ) ! (inout)
call DCArgsHelp( arg = arg ) ! (inout)
call DCArgsStrict( arg = arg ) ! (inout)
call DCArgsClose( arg = arg ) ! (inout)
end subroutine cmdline_optparse
end program #{@program_name}
EOF
if @lang_ja
return str.gsub(/\n?/m, '').gsub(/<\/ja>\n?/m, '')
else
return str.gsub(/.*?<\/ja>\n?/m, '')
end
end
end
#
# {dcmodel プログラミングガイドライン}[http://www.gfd-dennou.org/library/dcmodel/coding-rules/dcmodel-coding-rules.htm]に基づく
# Fortran 90/95 ソースコード (モジュール) のテストプログラム用
# NAMELIST ファイルの雛形となるコードを生成するためのクラス.
#
class DCModelF90SampleTestNmlMaker
include F90CodeChecker
attr_accessor :lang_ja
def initialize(quiet=nil)
@mod_name = 'dcmodel_sample_code'
@program_name = @mod_name + '_test'
@nml_group_name = @mod_name + '_nml'
@quiet = quiet
@author = 'unknown'
@copyright = 'GFD Dennou Club'
@lang_ja = true
end
#
# ファイル名としてふさわしい名前を返す.
#
def filename
return @program_name + '00.nml'
end
def set_modname(modname)
valid_f90entityname?(modname, true)
@mod_name = modname.to_s
@program_name = @mod_name + '_test'
end
def set_programname(programname)
valid_f90entityname?(programname, true)
@program_name = programname.to_s
end
def set_author(author)
@author = author
end
def set_copyright(copyright)
@copyright = copyright
end
#
# このメソッドを呼び出すと, コマンドライン上で
# インタラクティブに設定が行われる.
#
def interactive_setup
@mod_name = f90entityname_from_stdin(@mod_name, 'Module name')
print " Input Your name [#{@author}]: "
author = STDIN.gets.chomp
@author = author unless author == ''
print " Input Copyright [#{@copyright}]: "
copyright = STDIN.gets.chomp
@copyright = copyright unless copyright == ''
end
def to_s
str = ''
str << <<-EOF
#= #{@mod_name} モジュールのテストプログラム用 NAMELIST ファイル
#
#= NAMELIST file for test program of "#{@mod_name}"
#
# Authors:: #{@author}
# Version:: $#{}I#{}d: $
# Tag Name:: $#{}N#{}ame: $
# Copyright:: Copyright (C) #{@copyright}, #{Time.now.strftime("%Y")}. All rights reserved.
# License::
#
EOF
str << <<-EOF
{@mod_name}_nml
CoefAlpha=0.05, ! $ \\alpha $ . 係数. Coefficient
key00='keyword' ! キーワード. Keyword
/
{@mod_name}_history_nml
name = '',
! 変数名.
! 空白の場合には, 以下の設定値は
! デフォルトの設定として用いられる.
!
! Variable identifier.
! If blank is given, their values are
! used as default settings.
interval_value = 5.0,
!!$! interval_value = 10.0,
! ヒストリデータの出力間隔の数値.
! 負の値を与えると, 出力を抑止します.
!
! Numerical value for interval of history data output
! Negative values suppresses output.
interval_unit = 'sec',
!!$! interval_unit = 'min',
!!$! interval_unit = 'hrs',
!!$! interval_unit = 'day',
! ヒストリデータの出力間隔の単位.
! Unit for interval of history data output
precision = 'float',
!!$! precision = 'double',
! ヒストリデータの精度.
! Precision of history data
average = .false.,
!!$! average = .true.,
! 出力データの平均化フラグ.
! Flag for average of output data
fileprefix = 'NP_'
!!$! fileprefix = ''
!!$! fileprefix = 'data01/'
! ヒストリデータのファイル名の接頭詞.
! Prefixes of history data filenames
/
!!$!{@mod_name}_history_nml
!!$! name='Data1,Data2',
!!$! ! 変数名.
!!$! ! カンマで区切って並べることで,
!!$! ! 複数の変数に関する設定を一度に
!!$! ! 行うことができる.
!!$! ! (例: "Data1,Data2" ).
!!$! !
!!$! ! Variable identifier.
!!$! ! Multiple comma-deliminated variables
!!$! ! are configured at one time
!!$! ! (exp. "Data1,Data2" ).
!!$! file = ''
!!$! ! 出力ファイル名 (デフォルトは .nc).
!!$! ! Output file name (Default is ".nc").
!!$!/
!!${@mod_name}_history_nml
!!$ name='Data1',
!!$ ! 変数名. Variable identifier
!!$ file='NPI_Data1.nc'
!!$ ! 出力ファイル名 (デフォルトは .nc).
!!$ ! Output file name (Default is ".nc").
!!$/
!!${@mod_name}_history_nml
!!$ name='Data2',
!!$ ! 変数名. Variable identifier
!!$ average=.true.
!!$ ! 出力データの平均化フラグ.
!!$ ! Flag for average of output data
!!$/
EOF
if @lang_ja
return str.gsub(/\n?/m, '').gsub(/<\/ja>\n?/m, '')
else
return str.gsub(/.*?<\/ja>\n?/m, '')
end
end
end
#
# {dcmodel プログラミングガイドライン}[http://www.gfd-dennou.org/library/dcmodel/coding-rules/dcmodel-coding-rules.htm]に基づく
# Fortran 90/95 ソースコード (モジュール) のテストプログラム実行用
# シェルスクリプトの雛形となるコードを生成するためのクラス.
#
class DCModelF90SampleTestShMaker
include F90CodeChecker
attr_accessor :lang_ja
def initialize(quiet=nil)
@mod_name = 'dcmodel_sample_code'
@program_name = @mod_name + '_test'
@quiet = quiet
@author = 'unknown'
@copyright = 'GFD Dennou Club'
@lang_ja = true
end
#
# ファイル名としてふさわしい名前を返す.
#
def filename
return @program_name + '.sh'
end
def set_modname(modname)
valid_f90entityname?(modname, true)
@mod_name = modname.to_s
@program_name = @mod_name + '_test'
end
def set_programname(programname)
valid_f90entityname?(programname, true)
@program_name = programname.to_s
end
def set_author(author)
@author = author
end
def set_copyright(copyright)
@copyright = copyright
end
#
# このメソッドを呼び出すと, コマンドライン上で
# インタラクティブに設定が行われる.
#
def interactive_setup
@mod_name = f90entityname_from_stdin(@mod_name, 'Module name')
@program_name = @mod_name + '_test'
print " Input Your name [#{@author}]: "
author = STDIN.gets.chomp
@author = author unless author == ''
print " Input Copyright [#{@copyright}]: "
copyright = STDIN.gets.chomp
@copyright = copyright unless copyright == ''
end
def to_s
str = ''
str << <<-EOF
#!/bin/sh
#
#= Compile and Execute test program of "#{@mod_name}"
#
# Authors:: #{@author}
# Version:: $#{}I#{}d: $
# Tag Name:: $#{}N#{}ame: $
# Copyright:: Copyright (C) #{@copyright}, #{Time.now.strftime("%Y")}. All rights reserved.
# License::
#
######################################################################
#
#== Settings
test -n "$TEST_BASE" || TEST_BASE="#{@mod_name}"
TEST_OBJ="${TEST_BASE}.f90 ${TEST_BASE}_test.f90"
TEST_EXEC="${TEST_BASE}_test"
TEST_NML00="${TEST_BASE}_test00.nml"
test -n "$LINKF" || LINKF=gt4frt
#test -n "$MAKE" || MAKE=make
# End Settings
######################################################################
set -e
case `echo "testing\\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
*c*,-n*) ECHO_N= ECHO_C='
' ECHO_T=' ' ;;
*c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
*) ECHO_N= ECHO_C='\\c' ECHO_T= ;;
esac
echo ""
echo "****** ${TEST_BASE} Test ******"
echo " in \\"`pwd`\\""
echo " Compiling and Linking ... "
if [ -n "${LINKF}" ]; then
echo " ${LINKF} ${TEST_OBJ} -o ${TEST_EXEC}"
${LINKF} ${TEST_OBJ} -o ${TEST_EXEC}
else
${MAKE} ${TEST_EXEC}
fi
echo " done . "
if [ ! "$CROSS_COMPILING" = "yes" ] && [ ! "$CROSS_COMPILING" = "maybe" ] ; then
echo "./${TEST_EXEC} --namelist=${TEST_NML00}"
./${TEST_EXEC} --namelist=${TEST_NML00}
else
echo ""
echo " WARNING: Cross compile mode will be used."
echo " Submit ./${TEST_EXEC} ."
echo ""
exit 1
fi
echo " *** Test program \\"${TEST_EXEC}\\" becomes successful ***"
exit 0
EOF
if @lang_ja
return str.gsub(/\n?/m, '').gsub(/<\/ja>\n?/m, '')
else
return str.gsub(/.*?<\/ja>\n?/m, '')
end
end
end
end
#
# 以下はこのファイルを実行プログラムとして動かした際の動作.
#
if $0 == __FILE__
opt = OptionParser.new
OPTS = {}
ARGV.options{|opt|
opt.on( '-E=VAL', '--entity=VAL',
"kind of entity (ex. \"module\", \"procedure\")"
){|v| OPTS[:entity] = v.gsub(/^=/, '')}
opt.on( '-K=VAL', '--proc-kind=VAL',
"kind of procedure
(ex. \"create\", \"close\",
\"putline\", \"nmlread\")
\"settime\", \"calc\", \"sample\")"
){|v| OPTS[:proc_kind] = v.gsub(/^=/, '')}
opt.on( '-i', '--interactive',
"interactive setup (default)"
){|v| OPTS[:interactive] = v}
opt.on( '-f', '--overwrite',
"Overwrite existing files"
){|v| OPTS[:overwrite] = v}
opt.on( '--stdout',
"Output to standard output"
){|v| OPTS[:stdout] = v}
opt.on( '--stdout-test',
"Output test program to standard output (only entity = module)"
){|v| OPTS[:stdout_test] = v}
opt.on( '-o=VAL', '--output=VAL',
"Output to specified file
(default: .f90, or
.f90)"
){|v| OPTS[:output] = v.gsub(/^=/, '')}
opt.on( '--no-lang-ja',
"Japanese documents are not output"
){|v| OPTS[:no_lang_ja] = true}
opt.on( '--no-test',
"Test program is not output"
){|v| OPTS[:no_test] = v}
opt.on_tail('-q', '--quiet',
"non interactive setup"
){|v| OPTS[:quiet] = v}
opt.on_tail('-h', '-H', '--help',
"This help message is output"
){|v| OPTS[:help] = v}
opt.parse!
}
if OPTS[:help] || !(OPTS[:entity])
print <<-"EOF"
#{File.basename($0.to_s)}:
USAGE: #{File.basename($0.to_s)} -E=kind_of_entity [options]
OPTION: \n#{opt.to_a[1..-1].join("")}
EOF
exit
end
OPTS[:proc_kind] ||= 'sample'
dcf90sample = DCModelF90SampleMaker.new(OPTS[:entity], OPTS[:proc_kind], OPTS[:quiet])
if OPTS[:no_lang_ja]
dcf90sample.no_lang_ja
end
if OPTS[:interactive] || !(OPTS[:quiet])
dcf90sample.interactive_setup
end
if OPTS[:stdout_test]
print dcf90sample.test_to_s
elsif OPTS[:stdout]
print dcf90sample.to_s
else
ofile = OPTS[:output] || dcf90sample.filename
if File.exist?(ofile) && !(OPTS[:overwrite])
raise IOError, "\n Error: \"#{ofile}\" already exists.\n" +
" Remove \"#{ofile}\" or use option \"--overwrite\"\n"
end
STDOUT.print " Message: #{ofile} is generated ... "
File.open(ofile, 'w'){ |file|
file.puts(dcf90sample.to_s)
}
STDOUT.print "done.\n"
if OPTS[:entity] == 'module' && !(OPTS[:no_test])
if OPTS[:output]
if OPTS[:output] =~ /(\.f\d*)$/i
testfilebase = $~.pre_match
testfilesuffix = $1
else
testfilebase = OPTS[:output]
testfilesuffix = ''
end
testfilename = testfilebase + '_test' + testfilesuffix
testnmlfilename = testfilebase + '_test00.nml'
testshfilename = testfilebase + '_test.sh'
end
otestfile = testfilename || dcf90sample.test_filename
otestnmlfile = testnmlfilename || dcf90sample.testnml_filename
otestshfile = testshfilename || dcf90sample.testsh_filename
if File.exist?(otestfile) && !(OPTS[:overwrite])
raise IOError, "\n Error: \"#{otestfile}\" already exists.\n" +
" Remove \"#{otestfile}\" or use option \"--overwrite\"\n"
end
if File.exist?(otestnmlfile) && !(OPTS[:overwrite])
raise IOError, "\n Error: \"#{otestnmlfile}\" already exists.\n" +
" Remove \"#{otestnmlfile}\" or use option \"--overwrite\"\n"
end
if File.exist?(otestshfile) && !(OPTS[:overwrite])
raise IOError, "\n Error: \"#{otestshfile}\" already exists.\n" +
" Remove \"#{otestshfile}\" or use option \"--overwrite\"\n"
end
STDOUT.print " Message: #{otestfile} is generated ... "
File.open(otestfile, 'w'){ |file|
file.puts(dcf90sample.test_to_s)
}
STDOUT.print "done.\n"
STDOUT.print " Message: #{otestnmlfile} is generated ... "
File.open(otestnmlfile, 'w'){ |file|
file.puts(dcf90sample.testnml_to_s)
}
STDOUT.print "done.\n"
STDOUT.print " Message: #{otestshfile} is generated ... "
File.open(otestshfile, 'w'){ |file|
file.puts(dcf90sample.testsh_to_s)
}
STDOUT.print "done.\n"
end
end
end