多数のファイル出力を行うモデルでのデータ出力
概要
出力ファイルの数が多いモデルでは, 以下で紹介する gtool_historyauto モジュールを利用することで, 複数ファイルの出力やその出力の設定変更を簡単に行うことが可能です.
gtool_historyautoは データ出力のための最低限の設定 で紹介した gtool_history モジュールの拡張版で, 以下のような特徴を持ちます.
- 複数のファイルへの出力を行う場合, gtool_history モジュールでは ファイルごとに HistoryCreate を呼び出す 必要がありましたが, gtool_historyauto では HistoryAutoCreate をモデル内で一度呼び出す だけで済みます.
- 個別の変数について, 出力ファイル名や出力間隔を NAMELIST で手軽に変更可能です.
以下では gtool_historyauto モジュールの使い方を 説明します.
dc_date モジュールを使用する場合
バージョン 20090809 以前の gtool_historyauto では, dc_date モジュールを日付や時刻の扱いに使用しています. こちらの使い方に関しては, 多数のファイル出力を行うモデルでのデータ出力 (dc_date 版) を参照ください.
プログラム
プログラムとして, 階層的地球流体スペクトルモデル集 SPMODEL 一つである 球面上の流れ を計算するものを用います.
gtool_history を用いたものが sp_topo_gthist.f90 になります (上記ページで公開されるオリジナルから少し改変されています). このプログラムをコンパイル・実行すると, 4 つの従属変数 (h, u, v, zeta) が単一のファイル sp_topo_gthist.nc に出力されます. gtool_history でこれを別々のファイルに出力するには, 複数のファイルに出力 に示すように, ファイル毎に初期化サブルーチン HistoryCreate を指定せねばなりません.
gtool_historyauto を用いることで, 初期化サブルーチンの呼び出しが 一つで済むとともに, 変数ごとの出力設定の変更を容易に行うことができます.
gtool_historyauto を用いたサンプルプログラム
上記プログラムを gtool_historyauto を用いて書きなおしたものが 以下に示す sp_topo_gtauto_v2.f90 となります.
赤字(カラーがでない場合はボールド)が gtool_historyauto に 関係している箇所です. (行数が多いため, 一部を抜粋しています). 左の緑字は行数を表します.
このページでは各サブルーチンの詳細については述べません. 以下でサンプルプログラムの実行や NAMELIST による出力設定の変更を一通り試した後, 使われているサブルーチンの説明 を参照してください.
1 !---------------------------------------------------------------------- 2 ! Copyright (C) 2001--2008 SPMODEL Development Group. All rights reserved. 3 !---------------------------------------------------------------------- 4 ! Sample program for gtool_history/gtool5 and ISPACK 2002/08/21 S.Takehiro 5 ! 2004/01/26 M.Odaka 6 ! 2009/02/27 Y.Morikawa 7 ! 8 ! Solving a linear 2-D shallow water system on a sphere 9 ! with an isolated mountain 10 ! du/dt + u0/a\cos\phi du/d\lambda + v/a du0/d\phi - u0v\tan\phi/a 11 ! - 2\Omega\sin\phi v = -g/a\cos\phi dh/d\lambda - \nu\lapla^4 u, 12 ! dv/dt + u0/a\cos\phi dv/d\lambda + 2 u0 u \tan\phi/a 13 ! + 2\Omega\sin\phi u = -g/a dh/d\phi - \nu\lapla^4 v, 14 ! dh/dt + ( 1/\cos\phi d( (H+h0)u+(h-ht)u0 )/d\lambda 15 ! + 1/\cos\phi d( (H+h0)v\cos\phi)/d\phi ) = - \nu\lapla^4 h. 16 ! 17 ! A setup is similar to the experiment of Grose and Hoskins (1979) 18 ! with a superrotating rigid-rotation zonal wind profile. 19 ! 20 program sp_topo_gtauto_v2 21 22 use w_module 23 use gtool5 24 use gtool_historyauto ! モジュール指定 25 implicit none 26 27 !---- 空間解像度設定 ---- 28 integer, parameter :: im=64, jm=32 ! 格子点の設定(X,Y) 29 integer, parameter :: nm=21 30 31 !---- 変数 ---- 32 real(8) :: xy_U(0:im-1,jm) ! 格子点データ(速度経度成分) 33 real(8) :: xy_V(0:im-1,jm) ! 格子点データ(速度緯度成分) 34 real(8) :: xy_H(0:im-1,jm) ! 格子点データ(変位) : : 44 real(8) :: xy_Zeta(0:im-1,jm) ! 格子点データ(渦度) 45 real(8) :: xy_Htopo(0:im-1,jm) ! 格子点データ(地形) 46 47 !---- 時間積分パラメター ---- 48 real(8):: dt ! 時間間隔 [s] 49 real(8):: dispint ! 出力時間間隔 [s] 50 real(8):: endtime ! 計算終了時間 [s] 51 real(8):: ct ! 現在時刻 [s] : : 68 !------ NAMELIST ファイル名 ------ 69 character(*), parameter:: nmlfile = 'sp_topo_gtauto.nml' : : 75 !---- 時間積分パラメターの設定 ---- 76 dt = 100. ! 時間間隔 [s] 77 dispint = dt * 500 ! 出力時間間隔 78 endtime = dt * 10000 ! 計算終了時間 79 ct = 0. ! 現在時刻 80 81 82 !---------------- 座標値の設定 --------------------- 83 call w_Initial(nm,im,jm) ! ISPACK初期化 84 85 !------------------- 初期値設定 ---------------------- 86 xy_U0 = U0*cos(xy_Lat) 87 xy_H0 = ( Omega*R0*U0/(2*Grav) + U0**2/(4*Grav) )*cos(2*xy_Lat) 88 89 xy_U = 0 ; xy_V = 0 ; xy_H = 0 90 91 w_U0 = w_xy(xy_U0) !; w_H0 = w_xy(xy_H0) 92 w_U = w_xy(xy_U) ; w_V = w_xy(xy_V) ; w_H = w_xy(xy_H) : : 107 !------------------- ヒストリー初期設定 ---------------------- 108 call output_gtool5_init ! ヒストリー初期化 109 call output_gtool5 ! 初期値出力 110 111 !------------------- 時間積分 ---------------------- 112 do while ( ct <= endtime ) 113 if ( mod(ct, dispint) == 0.0d0 ) then 114 write(6,*) 'it = ', int( ct / dt ) 115 end if 116 117 ct = ct + dt ! 時刻の進行 118 119 w_U = ( w_U & 120 + dt * w_xy( - xy_U0 * xy_GradLon_w(w_U) / R0 & 121 - xy_V * xy_GradLat_w(w_U0) / R0 & 122 + xy_U0 * xy_V * tan(xy_Lat) / R0 & 123 + 2 * Omega * sin(xy_Lat) * xy_V & 124 - Grav * xy_GradLon_w(w_H)/ R0 ) & 125 )/(1+Nu*(-rn(:,1)/R0**2)**(ndiff/2)*dt) : : 144 xy_H = xy_w(w_H) 145 146 call output_gtool5 ! 出力 147 enddo 148 149 call output_gtool5_close ! ファイルのクローズ 150 stop 151 152 contains 153 subroutine output_gtool5_init 154 write(6,'(a)',advance='NO') ' Input NAMELIST file: ' 155 read (5,'(a)') nmlfile 156 157 call HistoryAutoCreate( & ! ヒストリー作成 158 title='Shallow water equation on a sphere', & 159 source='Sample program of gtool_historyauto/gtool5', & 160 institution='GFD_Dennou Club davis/spmodel project', & 161 dims=(/'lon','lat','t '/), dimsizes=(/im,jm,0/), & 162 longnames=(/'longitude','latitude ','time '/), & 163 units=(/'degree_east ','degree_north','sec. '/), & 164 origin=ct, interval=dispint, terminus=endtime, & 165 namelist_filename=nmlfile ) 166 167 call HistoryAutoPutAxis('lon',x_Lon*180/pi) ! 変数出力 168 call HistoryAutoAddAttr('lon','topology','circular') ! 周期属性 169 call HistoryAutoAddAttr('lon','modulo',360.0) ! 周期属性 170 call HistoryAutoPutAxis('lat',y_Lat*180/pi) ! 変数出力 171 172 call HistoryAutoAddVariable( & ! 変数定義 173 varname='h', dims=(/'lon','lat','t '/), & 174 longname='surface displacement ', units='m') 175 176 call HistoryAutoAddVariable( & ! 変数定義 177 varname='u', dims=(/'lon','lat','t '/), & 178 longname='velocity(longitude) ', units='m/s') 179 180 call HistoryAutoAddVariable( & ! 変数定義 181 varname='v', dims=(/'lon','lat','t '/), & 182 longname='velocity(latitude) ', units='m/s') 183 184 call HistoryAutoAddVariable( & ! 変数定義 185 varname='zeta', dims=(/'lon','lat','t '/), & 186 longname='vorticity', units='1/s') 187 188 end subroutine output_gtool5_init 189 190 subroutine output_gtool5 191 call HistoryAutoPut(ct, 'u', xy_U) 192 call HistoryAutoPut(ct, 'v', xy_V) 193 call HistoryAutoPut(ct, 'h', xy_H) 194 xy_Zeta = xy_w(w_Divlon_xy(xy_V) - w_Divlat_xy(xy_U))/r0 195 call HistoryAutoPut(ct, 'zeta', xy_Zeta) 196 end subroutine output_gtool5 197 198 subroutine output_gtool5_close 199 call HistoryAutoClose 200 end subroutine output_gtool5_close 201 202 end program sp_topo_gtauto_v2
コンパイルと実行
このプログラムを実際にコンパイルして実行してみましょう. まず, 上記ファイルと, 計算実行に必要なサブルーチンや関数の定義ファイル, およびサンプルとして使用する NAMELIST ファイルを以下からダウンロードしてください.
- sp_topo_gtauto_v2.f90
- ispack_snip.f
- w_module_snip.f90
- sp_topo_gtauto1.nml
- sp_topo_gtauto2.nml
- sp_topo_gtauto3.nml
次に, 計算に必要なサブルーチンや関数が含まれるファイルをコンパイルします. ispack_snip.f と w_module_snip.f90 を以下のようにコンパイルしてください.
$ gt5frt -c w_module_snip.f90 ispack_snip.f
コンパイルの結果, 5 つのファイル (w_module.mod, w_deriv_module.mod, w_base_module.mod, w_module_snip.o, ispack_snip.o) が作成されれば OK です. なお, ispack_snip.f と w_module_snip.f90 はそれぞれ, ISPACK ライブラリと spml ライブラリの一部を抜粋したものです.
sp_topo_gtauto_v2.f90 を以下のようにコンパイルしてください.
$ gt5frt sp_topo_gtauto_v2.f90 w_module_snip.o ispack_snip.o
これで実行ファイル a.out が作成されます. 以下のように実行してみましょう.
$ ./a.out
実行すると, 以下のようなメッセージが表示され NAMELIST ファイル名の入力 が求められます. まずは何も入力せずに Enter キーを入力しましょう.
Input NAMELIST file:
数秒から数分でプログラムが終了し, 4 つのファイル (u.nc, v.nc, h.nc, zeta.nc) が作成されます. これらのファイルには, それぞれ変数 (u, v, h, zeta) が格納されています.
NetCDF のコマンド ncdump を用いて中身を確認しましょう.
$ ncdump -v t u.nc | more
netcdf u { dimensions: lon = 32 ; lat = 16 ; t = UNLIMITED ; // (21 currently) variables: float lon(lon) ; lon:long_name = "longitude" ; lon:units = "degree_east" ; lon:topology = "circular" ; lon:modulo = 360.f ; float lat(lat) ; lat:long_name = "latitude" ; lat:units = "degree_north" ; float t(t) ; t:long_name = "time" ; t:units = "sec." ; float u(t, lat, lon) ; u:long_name = "velocity(longitude)" ; u:units = "m/s" ; // global attributes: :Conventions = "http://www.gfd-dennou.org/library/gtool4/conventions/" ; : data: t = 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000, 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000, 800000, 850000, 900000, 950000, 1000000 ; }
赤字(カラーがでない場合はボールド)を見ると, データが 50000 sec ごとに出力されていることがわかります. これは gtool_historyauto を用いたサンプルプログラム の 以下の個所での出力間隔の設定を反映したものです.
47 !---- 時間積分パラメター ---- 48 real(8):: dt ! 時間間隔 [s] 49 real(8):: dispint ! 出力時間間隔 : : 75 !---- 時間積分パラメターの設定 ---- 76 dt = 100. ! 時間間隔 [s] 77 dispint = dt * 500 ! 出力時間間隔 78 endtime = dt * 10000 ! 計算終了時間 : : 157 call HistoryAutoCreate( & ! ヒストリー作成 158 title='Shallow water equation on a sphere', & 159 source='Sample program of gtool_historyauto/gtool5', & 160 institution='GFD_Dennou Club davis/spmodel project', & 161 dims=(/'lon','lat','t '/), dimsizes=(/im,jm,0/), & 162 longnames=(/'longitude','latitude ','time '/), & 163 units=(/'degree_east ','degree_north','sec. '/), & 164 origin=ct, interval=dispint, terminus=endtime, & 165 namelist_filename=nmlfile ) 166
NAMELIST による出力間隔等の変更
NAMELIST ファイルを用いて出力間隔を変更してみます. 再度 a.out を実行します.
$ ./a.out
今回は以下のように NAMELIST ファイル名を入力してください.
Input NAMELIST file: sp_topo_gtauto1.nml ^^^^^^^^^^^^^^^^^^^ ← ここは手動で入力してください.
すると以下のメッセージが出力された後, 計算が実行されます.
*** MESSAGE [HistAuto] *** ----- "gtool_historyauto_nml" is loaded from "sp_topo_gtauto1.nml" ----- *** MESSAGE [HistAuto] *** Global Settings: *** MESSAGE [HistAuto] *** AllOutput = F *** MESSAGE [HistAuto] *** FilePrefix = *** MESSAGE [HistAuto] *** Interval = 1. [day] *** MESSAGE [HistAuto] *** Individual Settings: *** MESSAGE [HistAuto] *** Name = u, v, h, zeta *** MESSAGE [HistAuto] *** File = <Name>.nc *** MESSAGE [HistAuto] *** Interval = 1. [day]
今回も 4 つのファイル (u.nc, v.nc, h.nc, zeta.nc) が作成されます.
NetCDF のコマンド ncdump を用いて中身を確認しましょう.
$ ncdump -v t u.nc | more
netcdf u { dimensions: lon = 32 ; lat = 16 ; t = UNLIMITED ; // (21 currently) variables: : float t(t) ; t:long_name = "time" ; t:units = "day" ; float u(t, lat, lon) ; u:long_name = "velocity(longitude)" ; u:units = "m/s" ; // global attributes: :Conventions = "http://www.gfd-dennou.org/library/gtool4/conventions/" ; : data: t = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ; }
赤字(カラーがでない場合はボールド)を見ると, データが 1 day (= 86400 sec) ごとに出力されていることがわかります. これは sp_topo_gtauto1.nml の以下の個所での出力間隔の設定を反映したものです.
>ool_historyauto_nml IntValue = 1., ! 出力間隔の数値 IntUnit = 'day' ! 出力間隔の単位 / >ool_historyauto_nml Name = 'u, v, h, zeta' ! 出力変数 /
IntUnit には, "sec", "min", "hour", "day", "month", "year", "nondim" (無次元時間) などが使用可能です. 使用可能な単位については dc_date_typesの "Characters list for unit" を参照ください.
NAMELIST による変数ごとの個別出力設定
上記の例では, 全ての変数に対して一括の出力設定を行いましたが, 変数ごとに個別設定を行うことも可能です.
まず, 上記で作成したファイルを掃除しておきます.
$ rm -f u.nc v.nc h.nc zeta.nc
そして再度 a.out を実行します.
$ ./a.out
今回は以下のように NAMELIST ファイル名を入力してください.
Input NAMELIST file: sp_topo_gtauto2.nml ^^^^^^^^^^^^^^^^^^^ ← ここは手動で入力してください.
すると以下のメッセージが出力された後, 計算が実行されます.
*** MESSAGE [HistAuto] *** ----- "gtool_historyauto_nml" is loaded from "sp_topo_gtauto2.nml" ----- *** MESSAGE [HistAuto] *** Global Settings: *** MESSAGE [HistAuto] *** AllOutput = F *** MESSAGE [HistAuto] *** FilePrefix = *** MESSAGE [HistAuto] *** Interval = 1. [day] *** MESSAGE [HistAuto] *** Individual Settings: *** MESSAGE [HistAuto] *** Name = u, v *** MESSAGE [HistAuto] *** File = <Name>.nc *** MESSAGE [HistAuto] *** Interval = 12. [hour] *** MESSAGE [HistAuto] *** Individual Settings: *** MESSAGE [HistAuto] *** Name = zeta *** MESSAGE [HistAuto] *** File = <Name>.nc *** MESSAGE [HistAuto] *** Interval = 1. [day]
今回は 3 つのファイル (u.nc, v.nc, zeta.nc) が作成されます.
NetCDF のコマンド ncdump を用いて中身を確認しましょう.
$ ncdump -v t u.nc | more
: float t(t) ; t:long_name = "time" ; t:units = "hour" ; float u(t, lat, lon) ; u:long_name = "velocity(longitude)" ; u:units = "m/s" ; : data: t = 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, 168, 180, 192, 204, 216, 228, 240, 252, 264, 276 ; }
$ ncdump -v t zeta.nc | more
: float t(t) ; t:long_name = "time" ; t:units = "day" ; float zeta(t, lat, lon) ; zeta:long_name = "vorticity" ; zeta:units = "1/s" ; : data: t = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ; }
赤字(カラーがでない場合はボールド)を見ると, 変数 u は 12 hour おきに出力され, 一方で変数 zeta は 1 日おきに出力されていることがわかります.
これらは sp_topo_gtauto2.nml の以下の個所での出力間隔の設定を反映したものです.
- 赤字はすべての変数のデフォルトの出力設定となります. 変数 "zeta" はその変数名のみを記述したため, このデフォルトの出力設定に従って出力されました. (Name を与えないか, もしくは空文字を与えた場合に, それが デフォルト設定となります).
- 緑字は変数 "u" と "v" のみの出力設定となります. これは上記のデフォルト設定に上書きされるため, "u" および "v" についてはこの出力設定に従って出力されました.
- 変数 "h" は記述されていないため, 出力は行われませんでした.
! ! データ出力の全体設定 ! >ool_historyauto_nml IntValue = 1., ! 出力間隔の数値 IntUnit = 'day', ! 出力間隔の単位 / ! ! データ出力の個別設定 ! >ool_historyauto_nml Name = 'u, v' ! 出力変数 IntValue = 12., ! 出力間隔の数値 IntUnit = 'hour', ! 出力間隔の単位 / >ool_historyauto_nml Name = 'zeta' ! 出力変数 /
設定可能な項目
上記では出力間隔の変更を例に挙げましたが, gtool_historyauto ではこれだけでなく, 以下の項目を変更可能です. 一通りの設定が記述された NAMELIST ファイルを sp_topo_gtauto3.nml として用意しましたので, こちらを用いて設定変更をお試しください.
設定項目の一覧
- File
- (文字型) 出力ファイル名. 未指定もしくは空文字を指定した場合には, "<変数名>.nc" がファイル名となります.
- IntValue
- (実数型) 出力間隔の数値
- IntUnit
- (文字型) 出力間隔の単位
- Precision
- (文字型) データの精度. "float" (単精度実数型), "double" (倍精度実数型), "int" (整数型) を指定可能
- TimeAverage
- (論理型) データの時間平均フラグ. ".true." を与えると, 時間平均値が出力されます
- OriginValue
- (実数型) 出力開始時刻
- OriginUnit
- (文字型) 出力開始時刻の単位
- TerminusValue
- (実数型) 出力終了時刻
- TerminusUnit
- (文字型) 出力終了時刻の単位
- SliceStart
- (整数型配列) 空間方向の開始点. 空間方向に一部分のみ切り出して出力する場合に使用します. 以下の SliceEnd, SliceStride も同様です. 配列の 1 番目, 2 番目... が HistoryAutoCreate の dims に指定された次元に対応します.
- SliceEnd
- (整数型配列) 空間方向の終了点
- SliceStride
- (整数型配列) 空間方向の刻み幅
- SpaceAverage
- (論理型配列) 空間平均のフラグ. 配列の 1 番目, 2 番目... が HistoryAutoCreate の dims に指定された次元に対応します.
- NewFileIntValue
- (整数型) ファイル分割時間間隔. データを時間方向に分割する場合に使用します. 分割時には, ファイルの末尾に開始時刻に相当する数値が自動的に付加されます.
- NewFileIntUnit
- (文字型) ファイル分割時間間隔の単位
全体設定でのみ有効な設定項目
Name を指定しない, もしくは空文字を与えた場合, それは全ての変数に対するデフォルト設定となります.
その場合にのみ有効な項目として以下のものがあります.
- AllOutput
- (論理型) HistoryAutoAddVariable によってプログラム内で登録された変数を全て出力するためのフラグ. デフォルトではNAMELIST による変数ごとの個別出力設定に示すように, 変数は明示的に指定しない限り出力されませんが, この項目を ".true." とすることで, 全ての変数が出力されます.
- FilePrefix
- (文字型) データのファイル名の接頭詞. 例えば "exp1-" と指定すれば, 変数 "u" の出力ファイル名は (上記の項目 "File" で変数 "u" に対して明示的にファイル名を指定しない限りは) "exp1-u.nc" となります. また, "data01/" のようにスラッシュを含む文字列を指定することで, カレントディレクトリ以外の場所に出力するよう設定することも可能です.
サブルーチンの解説
gtool_historyauto を用いたサンプルプログラム で示した, gtool_historyauto の各サブルーチンおよびその引数については, 使われているサブルーチンの説明 を参照してください.
$Id: gtauto_first2.rd,v 1.1 2009-10-19 11:56:10 morikawa Exp $