[ English | 日本語 ] [ dcmodel ]

dcmodel プログラミングガイドライン

はじめに

dcmodel プログラミングガイドライン (旧 dcmodel コーディングルール. 以下, 本プログラミングガイドラインと称する) は Fortran 90/95 プログラムのソースコード書法, 更に実行プログラムの動作およびデータの入出力に関する スタイルを提案するものである.

本プログラミングガイドラインは以下の 2 点を目指して策定されている.

  • 読みやすいソースコードを作成すること.
  • 異なる数値モデル間でのソースコードの流用・交換を容易にすること.

本プログラミングガイドラインで想定している「読みやすいソースコード」とは, ソースコード中の演算実行部分からどのような計算を行っているか, ひいては元の支配方程式がどのようなものかを比較的簡単に想像できるものである. 読みやすいソースコードは, 改変しやすく, 管理もしやすい. このため, 本プログラミングガイドラインでは, 数式と対応させやすいソースコードを書 くための工夫に力点が置かれている.

本プログラミングガイドラインのソースコード書法の策定においては, ヨーロッパ・米国・日本の気象関係機関で作成されている既存の Fortran プログラムのプログラミングガイドライン ( 参考文献 1,2,3 ) を参考にした. なお, 本プログラミングガイドラインは dcmodel プロジェクトのモデル群の開発と共に検討, 修正を重ねていくものであり, 常に変更の可能性があることに注意されたい.

ルールの概要

ここでは, ソースコードならびにソースコードに埋め込まれる ソースコードリファレンスマニュアルの書法を定める.

  • 基本的な書法

    原則として気象庁標準コーディングルール ( 参考文献 1 ) に従う. ただし, いくつかの点において例外を設けた. 詳細は 基本的な書法 を参照すること.

  • 関数の利用

    数式演算では, サブルーチンではなく関数を用いる. これによりどの変数が返り値であるのか明確になり, 元の支配方程式と見かけが似たソースコードを作成することができる.

    関数名は 関数命名法 に従い命名する. これもソースコードを元の支配方程式の形により近づけるためである. (例: SPMODEL ( 参考文献 4 ))

  • 変数の命名

    変数名は 変数命名法 に従い命名する.

  • コメントの活用

    ソースコードの読みやすさを阻害しない範囲内で, 説明文(コメント)をソースコードに書く. 詳細は コメントの書き方 を参照せよ.

  • 統一したデータ入出力スタイル

    初期値データや計算結果データのなどの数値データの入出力, NAMELIST ファイルの入力は, 統一したスタイルの下で行う. 数値データの入出力は gt4f90io ( 参考文献 5 ) を用いて行う.

    詳細は, 入出力データ, リスタートファイルとヒストリーファイル, NAMELIST ファイルに関するルール を参照せよ.

  • モジュールとポインタの使用方法に関する規定

    モジュールとポインタは, モジュールとポインタの使用方法 の規定に従って使用する. これによりソースコードのトレース・管理が容易となる.

  • 文字定数の命名

    計算条件や状態を指定するような文字列は, 予約語として定める. 詳しくは 文字定数の命名法 (検討事項) を参照せよ.

  • 注: その他の文章

    数値モデルに関する文書には, 数理モデル解説(支配方程式系), 離散モデル解説(数理モデルの離散化), 各種ソフトウェア解説(ソフトウェア概説, 利用手引, 開発手引等), そして, ソースコードリファレンスマニュアル (個々のモジュール, 関数, サブルーチン等の説明) があるが, ここではソースコードにコメント行として埋め込まれ 自動生成される文章のみを念頭に置き, ソースコードに埋め込まれない文章に関する書法は別途定めることにする.

基本的な書法

原則として気象庁標準コーディングルール ( 参考文献 1 ) に従う.

ただし, 以下の例外を設ける.

  • 配列表記

    配列の演算では積極的に添字を廃止する. これはソースコードを 「数式のように書く」 ことに重きをおくためである.

    例えば, 単純な代入演算では

    x_PotTemp = x_Temp

    と書く. 上記の例では, 後述の 変数命名法 にしたがった変数名を用いている. 配列変数の名前に「次元情報に関する接頭詞」を付けることで, 配列の次元数が一目でわかるようにしている.

    これに対し, 気象庁標準コーディングルールでは,

    x_PotTemp(1:n) = x_Temp(1:n)

    というように配列添え字の上限下限を陽に書くことを求めている.

  • Fortran 95 機能の利用

    Fortran 95 の機能は利用してよい.

    気象庁標準コーディングルールでは 「最新の JIS 規格は Fortran 95 であるが, Fortran 90 しか使えない環境 が依然多い状況であると思われるので, Fortran 95 の新機能は当面使わない ことを推奨する.」 となっている. しかし, 現在フリーのものも含め, 大半の Fortran コンパイラで Fortran95 規格が利用可能なため, Fortran95 の機能の利用に関し制限は設けない.

  • 継続行の字下げ(インデンテーション)について

    継続行においては, 開始行から 2 桁下げたところに継続行を示す & をつける. & 記号の後に続く命令文の書き出し位置は可読性を損なわない範囲で自由とする.

    • 例 1 : 継続行の字下げの例

      Energy = VelXN**2 + VelYN**2 + xyr_VelZN**2  &
        &      + Gravity*Z + Cp*Temp

    エディタとして emacs を利用する場合, 付録 の内容を ~/.emacs に 追加すると良い.

変数命名法

基本ルール

配列型の変数名の基本形は以下のようにする.

(次元情報に関する接頭詞)_(物理的意味)(時間方向添字)

配列ではない変数名の基本形は以下のようにする.

(物理的意味)(時間方向添字)

時間方向に変化しない変数は (時間方向添字) を記述しない.

次元情報に関する接頭詞, 物理的意味, 時間方向添字の付け方については以下で説明する.

特定のモジュール, サブルーチン内でのみ現れる変数の名前については, その都度工夫して変数の名前を付けるようにする. 基本ルールに従わない変数の例については, 基本ルールに従わない変数名 を参照せよ.

次元情報に関する接頭詞・接尾詞

次元情報に関する接頭詞・接尾詞には, 以下の文字を用いる.

s  sin 展開スペクトルデータ
c  cos 展開スペクトルデータ
e  フーリエ展開スペクトルデータ
n  水平全波数スペクトルデータ
m  経度波数スペクトルデータ
w  球面調和関数展開スペクトルデータ(mn を 1 次元に格納)
l  ルジャンドル多項式データ
t  チェビシェフ多項式展開スペクトルデータ(端点で値をとる)
u  チェビシェフ多項式展開スペクトルデータ(中点で値をとる)
   b  チェビシェフ多項式の線形結合 (ノイマンーディレクレー)
   d  チェビシェフ多項式の線形結合 (両端ディレクレー)
   p  チェビシェフ多項式の線形結合 (ディレクレーノイマン)
   v  チェビシェフ多項式の線形結合 (両端ノイマン)
   f  チェビシェフ多項式の線形結合 (ディレクレーノイマン混合型)
   h  チェビシェフ多項式の線形結合 (ディレクレーノイマン混合型一般形)
   q  チェビシェフ多項式の線形結合 (ディリクレ+二階微分または一階微分がゼロ)
q  ヤコビ多項式データ
x  格子点データ(x / 経度座標)
y  格子点データ(y / 緯度座標)
z  格子点データ(z / 動径座標)
p  格子点データ半整数レベル(x / 経度座標)
q  格子点データ半整数レベル(y / 緯度座標)
r  格子点データ半整数レベル(z / 動径座標)
a  格子点データ(任意)
f  物質データ

今後検討を要する次元情報に関する接頭詞・接尾詞は以下のとおりである.

b  Bessel 関数展開スペクトルデータ 
h  エルミート多項式展開スペクトルデータ 
  • 例 1 : 1 次元配列である変数名の例

    p_Temp     x 方向 1 次元配列(半整数格子点)
    r_Temp     z 方向 1 次元配列(半整数格子点)
    z_Temp     z 方向 1 次元配列(整数格子点)
  • 例 2 : X-Z 2 次元座標における変数名の例

    pz: x 方向半整数格子点, z 方向整数格子点
    xr: x 方向整数格子点, z 方向半整数格子点
    xz: x 方向整数格子点, z 方向整数格子点
    
     Z
     |       |
    -pr--xr--pr-    
     |       |
     pz  xz  pz     
     |       |
    -pr--xr--pr-X
  • 例 3 : 3 次元スペクトルモデルにおける変数名の例

    xyz_Temp   整数レベル    (格子点データ)
    xyr_Temp   半整数レベル  (格子点データ)
    
    wz_Temp    整数レベル    (スペクトルデータ)
    wr_Temp    半整数レベル  (スペクトルデータ)

時間方向添字

時間方向の添え字には大文字を用いる. 未来のタイムステップを表すには A を, 現在のタイムステップを表すには N を, 過去のタイムステップを表すに B を用いる.

AA: 時刻 t+2Δt (After のさらに After)
A : 時刻 t+ Δt (After)
N : 時刻 t      (Now)
B : 時刻 t- Δt (Before)
BB: 時刻 t-2Δt (Before のさらに Before)

time split 等を用いた場合のように複数の時間レベルが現れる 場合には, 区別するための任意の文字を追加する.

As: 時刻 t+Δτ (短い時間刻で計算した After)
Al: 時刻 t+Δt  (長い時間刻で計算した After)

    Bl          Nl          Al
   -|-----------|-----------|---->t
   -|-----|-----|-----|-----|---->τ
    Bs    Ns    As    AAs
  • 例 4 : 時間方向添字を持つ変数名の例

    xy_TempA
    wa_VorB
    ss_ExnerNs

物理的意味

基本的なルール

  • 1 文字の名前はなるべく使用しない.

    悪い例

    T, ..., (U, V, W や X, Y, Z は例外とする)
  • 頭文字は大文字とする.
    • 例 1 : 変数名の例

      Temp, Vel, ...
  • ベクトル量にはその方向座標を示す添字を付ける
    • 例 2 : ベクトル量の変数名の例

      VelX, VelZ, TauX, TauZ, ...

個別名

複数の数値モデルにおいて必要となるであろう 名前について個別名を定める. 以下それらを列挙する. 個別名を定めるべきかどうかは適宜判断する必要が ある.

  • 座標等

    座標               X,  Lon (単位に応じて LonDeg (度数), LonRad (ラジアン) などとしても良いかもしれないが...??).
                       Y,  Lat
                       Z,  Rad, Press, Sigma
    
    交互格子点上の座標 x_X, p_X
                       y_Y, q_Y
                       z_Z, r_Z
    
    最大最小           *Max, *Min
    
    座標格子間隔       DelX, DelY, DelZ
                       DelLon, DelLat, DelRad
    
    暦                 Date            (?)
                       Date%Year, Date%Month, Date%Day, 
                       Date%Hour, Date%Min,   Date%Sec
    
    時間               Time
    
    時間格子間隔       DelTime
      長い時間ステップ DelTimeLong
      短い時間ステップ DelTimeShort
    
    時間ステップ数     Nstep           (?)
      長い時間ステップ NstepLong
      短い時間ステップ NstepShort
  • 予報変数

    座標               X, Lon
                       Y, Lat
                       Z, Rad
    
    速度               VelX, U, VLon, VelLon
                       VelY, V, VLat, VelLat
                       VelZ, W, VRad, VelRad, VelPress, VelSigma
    流線関数           Stream, Psi
    速度ポテンシャル   VelPot, Phi
    渦度               Vor,
                       VorX, ZLon
                       VorY, ZLat
                       VorZ, ZRad, Zeta
    ポテンシャル渦度   PV, PotVor
    水平発散           HDiv, HorDiv    (?)
    
    磁場               BX, BLon
                       BY, BLat
                       BZ, BRad
    電流               JX, JLon
                       JY, JLat
                       JZ, JRad
    
    温度               Temp 
    仮温度             VTemp, VirTemp
    温位               PTemp, PotTemp
    仮温位             VPTemp, VirPotTemp 
    相当温位           EqPTemp, EqPotTemp
    飽和相当温位       SatEqPTemp, SatEqPotTemp
    
    密度               Rho, Dens
    圧力               Press
    エクスナー関数     Exner
    ジオポテンシャル   GeoPot
    高度               Height
    
    トレーサ(4 次元配列にし, 4 番目の次元でトレーサの種類を区別する)
      分率(0〜1)       QMix, QTracer, QVap (記号 q を用いるから)
      混合比(0〜∞)    RMix, RTracer, RVap (記号 r を用いるから)
    
    降水量             Rain, Precip
  • 微分量

    時間微分の物理量を表す名前は D(従属変数)D(独立変数) と記述する.

    渦度の時間微分     DVorDtNs
    渦度の経度微分     DVorDlonNs
    相当温位の温位微分 DEqPotTempDPotTemp

今後検討を要する個別名

  • 平均成分 (検討事項)
    • 案 1 : 該当する変数名に Avr を接尾語につける.

      X 方向の速度の平均値  VelXAvr

      平均をとる座標が複数ある場合には Avr(平均をとる座標変数) のように すると良い.

      X 方向平均   VelXAvrX
      Y 方向平均   VelYAvrY
      Z 方向平均   VelZAvrZ
      水平平均     VelXAvrXY
    • 案 2 : Avr の代わりに Mean を用いても良い.

      X 方向の速度の平均値  VelXMean
      
      X 方向平均   VelXMeanX  
      Y 方向平均   VelYMeanY  
      Z 方向平均   VelZMeanZ  
      水平平均     VelXMeanXY 
  • 基本場 (検討事項)
    • 案 1 : 該当する変数名に Basic を接尾語につける.

      温度         TempBasic
      密度         RhoBasic
      圧力         PressBasic
      速度         VelXBasic

      欠点は, 変数名が長くなること.

パラメータの変数名 (検討事項)

円周率             Pi
ステファン-ボルツマン定数  ??
気体定数           GasConst

重力加速度         Grav
定圧比熱           Cp
定積比熱           Cv
非熱比             Gamma
自転角速度         Omega
気体分子量         Gaswt, MolWt
惑星名             Planet

文字定数の命名法 (検討事項)

計算条件, 状態を指定するような文字列を決めておいた方がよいかもしれない.

  • 案 1 : 境界条件を指定する文字列

    周期境界      'Cyclic'
    摩擦なし      'FreeSlip'
    滑べりなし    'RigidRid'
    放射条件      'Radiation'

各変数に対し境界条件を適用する下請けモジュールまたはサブルーチン内で スイッチなどに用いられる文字列は, 各数値モデルの実装に応じて決めてよい.

基本ルールに従わない変数名

数値モデルのソースコード中には, 変数命名法の基本ルールに従わない名前を持つ変数が存在していてもよい. それらの変数の名前は, それらしい意味を持った名前にする. 原則として数値モデルに関する文書に用いられている名前と対応した変数名にする.

式中に現れる個別の項

たとえば

dT/dt = ADV + DIFF

のように数値モデルに関する文書に書かれており, ADV, DIFF に対応 する変数を使用する場合には, ADV, DIFF に対応した変数名にする.

計算パラメータ

数値モデルに関する文書に記述されていない変数の名前は, それらしい意味 を持った名前をその都度考えて与える.

例えば, 計算パラメータの具体例としては, 時間差分に陰解法を用いた場合 の重み, 音波減衰項の係数, Asselin 時間フィルターの係数, 乱流エネルギー から拡散係数を求める際の比例係数, などが挙げられる.

行列の要素

数値モデルに関する文書には単に「逆行列を解く」とのみ記載されている場合, 実際の逆行列を解く部分で必要になる中間変数の変数名は, それらしい意味を持つものにする.

たとえば係数行列を LU 分解して解く場合, L 行列の要素は LL, U 行列の要素は UU などとする.

配列要素の大きさ

配列要素の大きさを表す変数もそれらしい名前を持たせる.

格子モデルのように, 「配列要素の大きさ」と「物理的に意味のあ る領域の大きさ」を区別する必要がある場合, 以下のように多少長めの変数名を付けておいた方がよいだろう. この場合の欠点は, 配列変数の宣言文が長くなることである.

  • 例 5 : 配列の上限と下限(配列要素の大きさ)を指定する変数の例

    imax, imin, jmax, jmin
  • 例 6 : 物理的に意味のある領域の大きさ(箱の大きさ)を指定する変数の例

    例1: XMax, XMin, PressMax, PressMin
    例2: Xmax, Xmin, Pressmax, Pressmin
  • 例 7 : のりしろ部分の大きさ(壁の大きさ)を指定する変数の例

    例1: XMargin, YMargin
    例2: Xmargin, Ymargin
作業領域
単に一時的に値を格納するためだけに用いられる変数の名前は Work にする.
Do ループ時に配列の要素を指定する変数
数値モデルに関する文書に用いられている添字と対応させやすい変数名にする.

関数命名法

基本ルール

関数名の基本形は以下のようにする.

(返り値の次元情報を示す接頭詞)_(機能)_(引数の次元情報を示す接尾詞)

ただし, 引数が複数である場合, さらにこの後ろに `_(引数の次元情報を示す接尾詞)' を引数の数だけ並べるようにする.

次元情報に関する接頭詞・接尾詞の具体例は 次元情報に関する接頭詞・接尾詞 を参照.

  • 例 1 : SPMODEL, 参考文献 1 における関数の例

    xy 2 次元データの          x_AvrLat_xy
    緯度方向平均を返す関数
    
    2 つの xy 2 次元データ
    に発散を作用させてスペ     w_Div_xy_xy
    クトルデータを返す関数

コメントの書き方

コメントの基本ルール

ソースコードファイルには, ファイル中のソースの要約, メインルーチン・モジュール・サブルーチン・関数の機能の要約, 変数・定数・引数・構造体の役割をコメント文として記述する. コメントは, RDOC Fortran90/95 ソースコード解析機能強化版(地球流体電脳倶楽部 dcmodel プロジェクト用) で処理ができる形式で書く.

コメントを付記することにより, ソースコードの読みやすさを向上させるとともに, RDoc のソースコード解析機能を用いてモジュール・サブルーチン・関数・変数・ 定数の仕様に関する解説文書を自動生成できるようにする.

コメントの書法

ファイル自体に関するコメントは, ファイルの一番最初に記述する.

メインルーチン・モジュール・サブルーチン・関数・構造体 に関するコメントは, それぞれ program, module, subroutine, function, type で始まる行よりも下の行に記述する.

サブルーチンや関数の引数・変数・定数に関するコメントは, 原則として, トレイリングコメント (行末に, コメント記号 ` ! ' 後に記述するコメント)として付記する. 記述する内容が行末のみに収まらない場合, 改行して以降の行に記述する. 改行の際, 行頭の位置はそろえる.

  • 例 1 : ファイル自体に関するコメント, 変数に関するコメント, サブルーチンに関するコメントの例

    ! (ファイルの行頭)
    !
    ! ファイルの情報をここに書く
    !
    module hogehoge
      !
      ! モジュール ( program の場合はメインルーチン ) の機能をここに書く
      !
    
      use constants, only: PI, Grav
    
      implicit none
    
      private
    
      public :: any_value, any_constant, MULTI_ARRAY
    
      real    :: any_value     ! 変数に対するコメント
      integer :: any_constant  ! 定数に対するコメント
    
      type MULTI_ARRAY
        !
        ! 構造体に対するコメントはここに書く
        !
        real, pointer :: var(:) =>null() ! 変数に対するコメント
        integer       :: num = 0         ! 変数に対するコメント
      end type MULTI_ARRAY
    
    contains
    
      subroutine hoge( inA,  inB,  & !(in)
        &              inout,      & !(inout)
        &              out         & !(out)
        &             )
        !
        ! サブルーチン ( function の場合は関数) の機能をここに書く
        !
        character(*),intent(in) :: inA ! 変数 A の説明が行末に
                                       ! 収まらない場合, このように書く
        character(*),intent(in) :: inB_longlonglonglonglonglong
                                       ! 変数 B が長くコメントが行末に
                                       ! 書けない場合, このように書く
        character(*),pointer :: inC    !(in) ポインタC
        character(*),pointer :: inout  !(inout) ポインタinout
        character(*),pointer :: out    !(out) ポインタout
    
        ...
    
      end subroutine hoge
    end module hogehoge

授受特性の記述

サブルーチンを呼び出す call 文の引数の後ろには, 授受特性をコメントで記述する. 見た目をそろえるため, subroutine 文にも同様に授受特性を記述する. なお, 引数の授受特性の後ろに引数の説明等を追記しても良い.

call 文に授受特性に関するコメントを付けるのは, サブルーチンの call 文だけでは引数の授受特性がわからないからである.

ポインタを引数に使用する場合は, 変数の定義文の後ろに入出力情報をコメントで記述する. ポインタの場合はソースコードに intent 属性を付記できないからである.

ソースコード例を 例 2 に示す.

(検討事項) 授受特性に加え, 割り付け状態がどのようになっているかを示す ことを推奨する. ソースコード例を 例 3 に示す. しかし, 授受特性が in と inout のポインタは既に割り付けられているべきであり, 一方で授受特性 が out のポインタは既に解放されているべきであることは明らかである. 従っ て, in, out, inout を指定すればポインタの割り付け状態を別途示す必要は ないかもしれない.

  • 例 2 : サブルーチンの授受特性に関するコメント, ポインタに関するコメントの例

    call hoge( inA, inB,         & !(in)
      &        inoutA, inoutB,   & !(inout)
      &        outA              & !(out) ポインタ出力変数
      &      )
    ...
    
    subroutine hoge( inA, inB,       & !(in)
      &              inoutA, inoutB, & !(inout)
      &              outA,           & !(out) ポインタ出力変数
      &              outB            & !(out)
      &            )
      character(*),intent(in) :: inA    ! 入力変数
      integer,pointer         :: inB    !(in) ポインタ入力変数
      real,pointer            :: inoutA !(inout) ポインタ入出力変数
      real                    :: inoutB ! 入出力変数
      real(8),pointer         :: outA   !(out) ポインタ出力変数
      logical, optional       :: outB   ! 出力変数
    
      ...
    
    end subroutine hoge
  • 例 3 : ポインタの割り付け状態を明記する場合の例 (検討事項)

    call hoge( inA,     & !(in)
      &        inB,     & !(in,allocated)
      &        inoutA,  & !(inout,allocated)
      &        inoutB,  & !(inout)
      &        outA,    & !(out,deallocated) ポインタ出力変数
      &        outB     & !(out)
      &      )
    ...
    
    subroutine hoge( inA,     & !(in)
      &              inB,     & !(in,allocated)
      &              inoutA,  & !(inout,allocated)
      &              inoutB,  & !(inout)
      &              outA,    & !(out,deallocated) ポインタ出力変数
      &              outB     & !(out)
      &          )
      character(*),intent(in) :: inA    ! 入力変数
      integer,pointer         :: inB    !(in) ポインタ入力変数
      real,pointer            :: inoutA !(inout) ポインタ入出力変数
      real                    :: inoutB ! 入出力変数
      real(8),pointer         :: outA   !(out) ポインタ出力変数
      logical, optional       :: outB   ! 出力変数
    
      ...
    
    end subroutine hoge

入出力データ

数値モデルに入出力するデータを格納したファイルは, 原則として, NAMELIST ファイル , リスタートファイル, ヒストリーファイルの 3 種類であるとする.

リスタートファイルとヒストリーファイルの詳細に関しては リスタートファイルとヒストリーファイル を参照せよ. NAMELIST ファイルに関しては, NAMELIST ファイルに関するルールを参照せよ.

データの入出力には, gtool4 プロジェクトの データ I/O ライブラリ gt4f90io ( 参考文献 5 ) を使用する. 入出力インターフェースの形式をそろえることにより, 複数の数値モデルにおけるソースの読みやすさを高める.

入力データ

原則的に, 計算の開始時において, リスタートファイルと NAMELIST ファイルとの組を入力する.

リスタートファイルには初期値としての数値データが格納される. NAMELIST ファイルにはリスタートファイルの名前や各種パラメータの値の設定などを記述する. NAMELIST ファイル内でリスタートファイル名を指定しない場合には, プログラムの内部でデフォルトの初期値を作成し, その初期値からプログラムをスタートさせる. 各種のパラメータは NAMELISTファイル内で指定するものを用いる.

NAMELIST ファイル名を与えずにプログラムを実行した場合, プログラム内部でデフォルトの初期値を生成し, その初期値から プログラムをスタートさせる. 各種のパラメータはデフォルトのものを用いる.

出力データ

計算の実行中および実行終了時には, 必要に応じてリスタートファイルとヒストリーファイルを出力する.

数値モデルが出力するデータに与えるデータ時刻としては, 入力するリスタートファイルのデータ時刻を引き継いだもの, およびモデル時刻の両方が許容されていなければならない. どちらの方法を選択するかの指定は NAMELIST ファイルでなされるように なっていなければならない.

ここで, モデル時刻とは数値モデル中の積分時間を指し, データ時刻とは入出力するデータに与えられる時刻を指す. 以下の例を参照せよ.

  • 例 1 : NCEP の 2000 年 1 月 1 日のデータを初期値に与えて 1 年積分する場合の例

    モデル時刻                              : 0 日 〜 1 年
    初期値データのデータ時刻                : 2000 年 1 月 1 日
    出力されるリスタートファイルのデータ時刻: 2000 年 12 月 31 日 
  • 例 2 : 理想的な初期値を与えて 1 年積分する場合の例

    モデル時刻                              : 0 日 〜 1 年
    初期値データのデータ時刻                : 0 日
    出力されるリスタートファイルのデータ時刻: 1 年

リスタートファイルとヒストリーファイル

数値モデルは, リスタートファイルとヒストリーファイルを別々のファイルに分けて出力する. リスタートファイルとヒストリーファイルとを分けるのは, 出力する個々のデータがリスタートに必要なのか不要なのかを明確にする利点があるからである.

リスタートファイルとヒストリーファイルの説明は以下の通りである.

リスタートファイル

いわゆる初期値として必要なデータや継続実験 を行うためのデータ(リスタートデータ)を格納するファイルである. 格納されるデータの種類はプログラムによって異なる.

1 つのリスタートファイルには, 継続実験を行うためにに必要なデータ全てを 出力すること. 正しくリスタートを行うため, プログラム内で用いる最も高い精度と同じ精度のデータを格納する.

プログラムのスタート, リスタートに不要なデータは含まないようにする.

リスタートファイルの出力のタイミングは任意だが, プログラム終了時には必ず出力する.

ヒストリーファイル

プログラムによって生成された結果のデータを出力するファイルである. 多くの場合, 特定の変数の時系列データが格納される.

ヒストリーファイルにはプログラム実行者が必要とするデータを任意で出力する. 必要となるデータは場合によって異なるため, 出力する変数の種類や データを書き出すタイミングはプログラム実行者によって決められる. 複数のデータを 1 つのファイルにまとめても, 複数のファイルに分けても良い. 精度もプログラム実行者が決めて良い.

ヒストリーファイルにモデル時刻ゼロのデータ (プログラムを実行する際に入力した リスタートファイルのデータ) を出力したい場合もあろう. モデル時刻ゼロのデータを出力できるかどうか, NAMELIST によって動的に 変化できるようにしておくべきである. デフォルトの動作としては, リスタートファイルを入力する際には出力し, 初期値データを自身で生成する際には出力しない, とするのが良いように思われる.

平均値を計算する際に座標重みを必要とする数値データの場合には, 座標重みのデータも各ヒストリーファイルに格納することを推奨する.

ヒストリーファイルの名称について

個々のヒストリーファイルに特定の変数の時系列データを格納する場合, そのファイル名はソースコード内で使用されている変数名の物理的意味 をあらわす文字列(例: 変数名が xyz_Temp であれば Temp の部分)を 含んだものとすることを推奨する.

  • 例 1 : 実験名が SyncRot である数値実験結果の 100 日目から 200 日目までの温度のヒストリーファイル名

    SyncRot_Temp_Day100-200.nc

NAMELIST ファイルに関するルール

NAMELIST ファイルの書法

NAMELIST ファイルには, 入力する定数/変数の説明を以下の形式のコメントで記述する.

  • 例 1 : NAMELIST ファイルの例

    #--------------------------- 物理変数設定 ----------------------------
    #
    #  real(8)   :: Radius             ! 球の半径
    #  real(8)   :: Omega              ! 回転角速度
    #  integer   :: HVOrder            ! 超粘性の次数(1 で普通の粘性,
    #                                  ! 水平ラプラシアンの階数)
    #  real(8)   :: HVisc              ! 超粘性係数
    
    &physics  Radius=1.0D0, Omega=100.0D0, HVOrder=8, HVisc=1.0D-21 / 
    
    ...

NAMELIST ファイル名の取得方法

NAMELIST ファイル名の取得には組み込み関数 getarg を使用する.

この方法を採用する理由は以下の通りである.

  • 実行のたびに NAMELIST ファイル名を動的に変化させることが 可能である.

    NAMELIST ファイルをハードコードするのに対し, ファイル名を 自由に変更できるため, 実験の際の手間を減らすことができる.

  • 標準入力ではなくファイルから取得するため, NAMELIST 変数の 順序を気にしなくて良い.

    プログラムが大規模になると読み込む NAMELIST 変数の数も 増大することが想定される. 標準入力からの読み込みと異なり, ファイルから読み込む場合にはファイル内を何度も参照可能なためである.

この方法には以下の欠点も指摘されている.

  • 組み込み関数 getarg は Fortran 95 の規格には含まれていない.

    しかし, ほとんどの処理系には用意されているので getarg を 使っても大きな問題は発生しないであろうと判断した.

  • 処理系によって getarg の仕様が異なる.

    処理系依存性の問題は, gtool4 プロジェクトの データ I/O ライブラリ gt4f90io ( 参考文献 5 ) で 対応することにより解決する予定である.

NAMELIST 変数のデフォルト値の設定

NAMELIST 変数で入力する値にはプログラム内部でデフォルト値を設定し, NAMELIST 変数が入力できない場合 (NAMELIST ファイル内に変数が 記述されていない場合) にもなんらかの値が設定されるようにする. これは, NAMELIST 変数が無くても正常に動作が続くことを強制する のではなく, 場合によってはプログラムを終了させることも含む.

これにより不定な変数がプログラム内で用いられるのを防ぐことができ, 結果として予期しない動作を抑止することができる.

モジュールとポインタの使用方法

モジュールを使用する際の注意

  • public 属性は明示的に与える.

    モジュール内で定義される定数・変数・関数・サブルーチン・構造体・ 利用者定義演算子・利用者定義代入は, デフォルトでは private 属性とし, 外部から参照される ものにのみ明示的に public 属性を与える. これにより, そのモジュールが何を公開するのかが明確になる.

  • 必ず only を用いる.

    モジュールを参照する際, 利用する定数・変数・関数・ サブルーチン・構造体・利用者定義演算子・利用者定義代入 には明示的に only をつけて参照する. これにより, そのソースコードを読む際 どのモジュールから何を参照したのかトレースが容易になる.

    • 例 1 : public 属性と only の使用例

      module sample_mod1
      
        use grid, only : DimXMax, DimYMax      ! 必ず only を用いて参照する
      
        implicit none
      
        private                                ! private 属性をデフォルトに
      
        public :: pub_sub1                     ! 外部から使用可
      
      contains
      
        subroutine public_sub       ! 外部から参照されるサブルーチン
      
          ...
      
        end subroutine public_sub
      
      
        subroutine internal_sub     ! 内部的に利用するサブルーチン
      
          ...
      
        end subroutine internal_sub
      
        ....
      
      end module sample_mod1
  • use により参照した他のモジュールの要素を public で公開する場合には「孫引き」であることを明示する.

    あるモジュールにおいて, use により参照した他のモジュールのサブルーチン, 関数, 変数, 定数, 構造体, 利用者定義演算子, 利用者定義代入のいずれかを 公開する場合には, それらが「孫引き」であること明示するために public 属性 の指定部分にトレイリングコメントとして "Cascaded" の文字列を付すること. 例を参照せよ. このように明示することで, ソースコードを解読する際, 各要素のトレースが容易になる.

    • 例 2 : 孫引きを明示した例

      module upper
      
        use lower, only: base1, base2
      
        private
      
        public :: base1, base2  ! Cascaded
      
        public :: app1, app2
      
        interface app1
      
          ...
      
        end interface 
      
      contains
      
        subroutine app2
      
          ...
      
        end subroutine app2
      
      end module upper

ポインタを使用する際の注意

  • null() による初期化をおこなう.

    ポインタを利用する際は, サブルーチンや関数の引数に用いる 場合を除き, 以下に示すように必ず null() による初期化を行う. これによりポインタの不定状態を回避することができ, associated 関数を安心して利用できる.

    • 例 3 : ポインタの初期化の例

      integer, pointer :: ptr(:) => null()
  • 引数に用いる場合には, 授受特性に関するコメントを付加する.

    ポインタを関数やサブルーチンの引数として用いる場合, ソースコード内に授受特性 (intent(in)などの属性) を付記することが できない. そのため, 実際の役割に応じて必ずコメントをつける. コメントの書き方 を参照せよ.

参考文献

  1. 気象庁標準コーディングルール
  2. ヨーロピアンスタンダード ( オリジナル / 気象研究所による和訳 )
  3. The GFDL Flexible Modeling System (FMS) のコーディングマニュアル
  4. 階層的地球流体スペクトルモデル集 SPMODEL
  5. gtool4 プロジェクト
  6. RDOC Fortran90/95 ソースコード解析機能強化版(地球流体電脳倶楽部 dcmodel プロジェクト用)

付録

  1. emacs 利用の際に Tab キーで字下げを行う時に

    このファイルに書きこまれる内容を ~/.emacs に追加することで, タブによる自動字下げの文字数を気象庁標準コーディングルールに 合わせることができる.

関連する URL

使用上の注意とライセンス規定

ライセンス規定

dcmodel プログラミングガイドラインに関する全ての権利は dcmodel プログラミングガイドライン作成メンバーに属する. dcmodel プログラミングガイドラインは「無保証・無責任」の原則 の元で利用が可能である. dcmodel プログラミングガイドラインを利用することによって生じる いかなる結果に対しても dcmodel プログラミングガイドライン作成メンバーは責任を 持たない. 変更の有無に関わらず, 上記著作権表示・責任限定規定・および本条件 書を必ず含める限りにおいて dcmodel プログラミングガイドラインを再配布してかまわない.

使用上の注意

dcmodel プログラミングガイドラインは, 研究・教育の場で用いられることを前提とし ています. 利用する場合には上記の正式なライセンス規定に従ってくださ い. 教育現場においては自由に使用・改変・再配布していただいて結構です.

dcmodel プログラミングガイドラインを利用して得られた科学技術的成果を論文や Web 等 にて発表する際には, その旨を記し, リファレンス等に挙げて頂くようお願いします.

引用例 (和文)
地球流体電脳倶楽部 dcmodel プロジェクト, 2008: dcmodel プログラミングガイドライン, http://www.gfd-dennou.org/library/dcmodel/, 地球流体電脳倶楽部.
引用例 (英文)
GFD Dennou Club Dcmodel Project, 2008: dcmodel programming guideline, http://www.gfd-dennou.org/library/dcmodel/, GFD Dennou Club.

dcmodel プログラミングガイドライン作成メンバー

2009 年度

石渡 正樹, 小高 正嗣, 佐々木 洋平, 杉山 耕一朗, 高橋 芳幸, 竹広 真一, 中島 健介, 林 祥介, 堀之内 武, 森川 靖大, 納多 哲史, 山下 達也

2008 年度

石渡 正樹, 小高 正嗣, 佐々木 洋平, 杉山 耕一朗, 高橋 芳幸, 竹広 真一, 中島 健介, 林 祥介, 堀之内 武, 森川 靖大, 山田 由貴子, 納多 哲史, 山下 達也

2007 年度

石渡 正樹, 小高 正嗣, 佐々木 洋平, 杉山 耕一朗, 高橋 芳幸, 竹広 真一, 中島 健介, 林 祥介, 堀之内 武, 森川 靖大, 山田 由貴子

2006 年度

石渡 正樹, 小高 正嗣, 杉山 耕一朗, 高橋 芳幸, 竹広 真一, 中島 健介, 林 祥介, 堀之内 武, 森川 靖大, 山田 由貴子

2005 年度

石渡 正樹, 小高 正嗣, 柿並 義宏, 北守 太一, 杉山 耕一朗, 高橋 芳幸, 竹広 真一, 谷口 博, 中島 健介, 林 祥介, 堀之内 武, 森川 靖大, 山田 由貴子

2004 年度

石渡 正樹, 小高 正嗣, 北守 太一, 杉山 耕一朗, 高橋 芳幸, 中島 健介, 林 祥介, 森川 靖大, 山田 由貴子