MRI.COM
目次
MRI.COM コーディングの基本方針
Fortran
配列
サブルーチン
引数:配列
引数:ポインター
引数:構造体
その他
必須
推奨
使ってもいいもの
避けた方がいいもの
禁止
MRI.COM コーディングの基本方針
Fortran
使用言語: Fortran95
Fortran2003 の命令を使う場合は #ifdef OGCM_F2003 で囲む
基本的には
気象庁 Fortran 標準コーディングルール
に準拠する
配列
通常、配列はimx,jmx,kmのサイズで宣言する
使用する範囲はコア+マージン領域である(1:imu,1:jmu)
それより外側のグリッドは使わないので、初期値も与えない
間違って外側グリッドを参照していれば、初期値にNaNを入れるオプションで検出できる
(1:imu,1:jmu)内の陸グリッドは -9.99d33 の欠損値を与える
マスク配列を使ってゼロをかければ使っても良いため
有効値が入ってる水平グリッド範囲は、配列によって2種類ある
コアのみ (ibt:iet,jbt:jet), (ibu:ieu,jbu:jeu)
次ステップ(いわゆるa系)の配列
モニター用配列
袖のために不要な重い計算や通信が発生する配列 (サブルーチン引数宣言のコメントで「コアのみ」と明示)
マージンには陸欠損値(-9.99e33)を入れる
コア+マージン (1:imu,1:jmu)
上記以外の配列
値の入力に不要な袖領域計算が必要になりうるが、目をつぶる
各MPIノードの配列サイズは実行時の標準出力で表示される
配列の動的割付では、使い終わったらdeallocateする。
サブルーチン
DRY(Don't Repert Yourself)原則:2回以上出てくるコード、ロジックはサブルーチン化する。
引数:配列
intentの指定は必須とする
Fortran規約では、intent(out) の場合、サブルーチンを呼ぶ前に入ってた値は無視され不定となる。
常にコア+マージン領域(1:imu,1:jmu)の範囲に値を入れて返すようにする
コア領域のみ有効値の配列については、マージン領域に陸欠損値(-9.99e33)を入れる
詳細は
Fortran 引数配列
allocatable配列を実引数にするとき、allocateせずにcallしてしまうと実行エラーとなる場合がある。allocateしておく。
引数:ポインター
F95 ではサブルーチンの中でポインターと宣言した引数にintent属性を付けられないのに注意
引数:構造体
サブルーチン、関数で構造体を仮引数にする場合、同じモジュール内でtype宣言するか、サブルーチン内でuseしなければならない。
サブルーチンの外側(モジュール冒頭など)でuseすると、frontでレベル04エラーとなる。
その他
必須
ログメッセージの標準出力は「write(*,*)」ではなくて「write(6,*)」を使う。
(*,*)の出力先がマシンによって異なるため。
推奨
いわゆるガード節を使って、ifのネストを浅くする
例外処理を本処理の前に書く
i,j,k等のdoループ内のマスク配列の使用
if文が入るとベクトル(SIMD)並列されないため (
FX100, CX2550で検証
) ←$!omp simdで再検証
Cray機 ifort, crayftn ではif文の方が速いらしい
数年後に再検討?
制御側のcall呼び出しスキップ
特定の条件でサブルーチンをスキップする場合は、制御(呼び出し役、デザインパターンで言うFacade)でスキップ
ただし、呼ばれる側の内部ロジカル変数に依存してスキップする場合は、サブルーチンの冒頭でreturnする
使ってもいいもの
オプショナル変数
避けた方がいいもの
ポインタ
ただし、参照のみ、ローカルな使用(サブルーチン終わりにnullify)、それでコードが分かりやすくなる場合には許す。
サブルーチン内のsave宣言: module冒頭に移した方が良い
状態遷移を抑制するため、save属性変数への代入はiniのみで行うべき。
スコープは広くなってしまうが、モジュールで確保されるメモリが分かりやすい
OpenMP によるスレッド並列では、モジュール変数は shared、サブルーチン内変数は private となるのがデフォルトの動作
禁止