計算をリスタートする時の処理がうまく行ってなかったんだが、shスクリプトとsed,awkをあれこれして何とかクリア。次は、並列計算の対応。
今回の場合、外部連携プログラム(Fortran)を動かすのに、OFに含まれるsystemCallを用いて起動shスクリプトを叩いている。このままでは、並列計算のときに全てのプロセスが外部連携プログラムを起動してしまい、うまくないので、上記のサイトの下に記載してあるやり方で調べてみた。
こんな感じ↓です。
(1)systemCallを使うためにOpenFOAM-2.2.x/etc/controlDictを変更
// Allow case-supplied C++ code (#codeStream, codedFixedValue)
allowSystemOperations 1; // 0だと使用許可しない。
(2)caseファイルのsystem/controlDictにsystemCall function objectを記述
sysCall
{
type systemCall;
functionObjectLibs ( "libsystemCall.so" );
executeCalls 1("sh ./runTime.sh"); // 各タイムステップの実行時に1回だけ起動(数字は()内の引数の数で複数並べるなら 2("hoge" "fuga")となる。
endCalls 1("sh ./runTime.sh"); // 全ての時間ステップが終わったら1回だけ実行
writeCalls 1("echo Writing to file call"); // ファイルに出力するタイミングで実行
outputControl timeStep;
outputInterval 1;
}
(3)runTime.shの書き換え
MPI計算時に発生する環境変数を見て、マスタープロセスのみで実行するように書き換える。OF標準のOpenMPIなら、"$OMPI_COMM_WORLD_RANK" (各プロセスのRANK) "$OMPI_COMM_WORLD_SIZE"(全体のプロセス数)などの環境変数が生成されるので、
if [ $OMPI_COMM_WORLD_RANK = 0 ]; then // RANK 0だけで実行 echo "Do what the master needs to do." fi
という感じにすればよさそう。
$ cat OpenMPI_echo.sh
#!/bin/sh
if [ $OMPI_COMM_WORLD_RANK = 0 ];then
echo "This is "$OMPI_COMM_WORLD_RANK" of "$OMPI_COMM_WORLD_SIZE
fi
$ mpirun -np 4 sh ./OpenMPI_echo.sh
This is 0 of 4
という感じで、予定通りうまく行った。shスクリプトを思い出すほうが時間がかかった。でも、まだまだ汎用的ではないですな。