計算の確認と計算結果の処理

2021年6月20日

はじめに

計算の確認と計算結果の処理について。

使用バージョン

OpenFOAM v2012、v8

残差の確認

function object を用いる方法

残差を出力するには function object という機能を用いる。OpenCFD 版 v3.0+ 以降では、system/controlDict で次のように設定する。

functions
{
    #includeFunc solverInfo
}

デフォルトでは U と p の残差だけ表示するようになっている。残差を表示する変数を指定するには、次のように書けばよい。

functions
{
    #includeFunc solverInfo(U,p,k,epsilon)
}

あるいは、次のように書いてもよい。

functions
{
    residuals
    {   
        type            solverInfo;
        libs            ("libutilityFunctionObjects.so");
        fields          (U p k epsilon);
    }
}

後者が本来の function object の書き方で、"#includeFunc" のほうは短縮系のようなものである。実際には、$FOAM_ETC/caseDicts/postProcessing/numerical/solverInfo を読み込んでいる。

libs は、OpenCFD 版では "libutilityFunctionObjects.so" の代わりに、引用符なしで utilityFunctionObjects と書いてもよい。

すべてのフィールドを指定するには次のように書ける。

functions
{
    residuals
    {   
        type            solverInfo;
        libs            ("libutilityFunctionObjects.so");
        fields          (".*");
    }
}

ソルバーを実行すると、"postProcessing" ディレクトリの中にテキストデータが出力される。グラフを表示するには、foamMonitor を用いる (gnuplot が必要)。

$ foamMonitor -l postProcessing/solverInfo/0/solverInfo.dat

ただし、残差以外の余計な情報も表示される。気に入らなければ gnuplot などで自分でグラフを描けばよい。

writeResidualFields を有効にすると、残差の分布を書き出すことができる。

functions
{
    residuals
    {   
        type            solverInfo;
        libs            ("libutilityFunctionObjects.so");
        fields          (".*");
        writeResidualFields yes;
        writeControl    outputTime;
    }
}

計算結果の中に "initialResidual:Ux" といったフィールドができる。

OpenCFD 版 v1812 以前および Foundation 版

バージョン 2.4.0 から、残差を出力する function object が使える。system/controlDict で次のように設定する。

system/controlDict

functions
{
    #includeFunc residuals
}

デフォルトでは p と U の残差だけ表示するようになっている。残差を表示する変数を指定するには、次のようにする。

system/controlDict

functions
{
    #includeFunc residuals(U,p,k,epsilon)
}

あるいは、次のように書いてもよい。

system/controlDict

functions
{
    residuals
    {
        type            residuals;
        libs            ("libutilityFunctionObjects.so");
        fields          (U p);
    }
}

ソルバーを実行すると、"postProcessing" ディレクトリの中にテキストデータが出力される。グラフを表示するには、foamMonitor を用いる。

$ foamMonitor -l postProcessing/residuals/0/residuals.dat

バージョン 3.0.x 以前

バージョン 3.0.x 以前では、以下のようにする。

functions
{
    residuals
    {
        type            residuals;
        functionObjectLibs ("libutilityFunctionObjects.so");
        fields          (U p);
    }
}

計算ログから残差を得る方法

ソルバーの出力を log ファイルとして保存してあれば、つぎのようにして残差の情報を取り出すことができる。

$ foamLog log

logs というディレクトリが作成され、中に各変数の残差の情報が入る。これらを gnuplot などでプロットすれば、残差の傾向がわかる。たとえば、つぎのようなスクリプトを用意しておく。

plot

#!/usr/bin/gnuplot -persist

set title 'Residuals'
set xlabel 'Time'
set ylabel 'Initial residual'
set logscale y
set format y "%.0e"
set grid

plot   'logs/Ux_0' title 'Ux' w l
replot 'logs/Uy_0' title 'Uy' w l
replot 'logs/Uz_0' title 'Uz' w l
replot 'logs/p_0' title 'p' w l
replot 'logs/p_rgh_0' title 'p_rgh' w l
replot 'logs/T_0' title 'T' w l
replot 'logs/h_0' title 'h' w l
replot 'logs/k_0' title 'k' w l
replot 'logs/epsilon_0' title 'epsilon' w l
replot 'logs/omega_0' title 'omega' w l
replot 'logs/Rxx_0' title 'Rxx' w l
replot 'logs/Rxy_0' title 'Rxy' w l
replot 'logs/Rxz_0' title 'Rxz' w l
replot 'logs/Ryy_0' title 'Ryy' w l
replot 'logs/Ryz_0' title 'Ryz' w l
replot 'logs/Rzz_0' title 'Rzz' w l

set terminal png
set output 'residual.png'
replot

これは単純だがあまりスマートではない。つぎのように存在するファイルだけ表示させたらよいかもしれない。

#!/bin/sh

VARS=`ls logs | grep FinalRes | sed -e 's/FinalRes_0//'`
if [ "$VARS" = "" ] ; then
    VARS=`ls logs | sed -e 's/_0//'`
fi

DIR=logs

PLOT=""
HEAD=1

for VAR in $VARS ; do
    if [ -e "logs/${VAR}_0" ] ; then
        if [ $HEAD -eq 1 ] ; then
            PLOT="plot 'logs/${VAR}_0' title '$VAR' w l"
            HEAD=0
        else
            PLOT="$PLOT, 'logs/${VAR}_0' title '$VAR' w l"
        fi
    fi
done

gnuplot -p <<EOF
set title 'Residuals'
set xlabel 'Time'
set ylabel 'Initial residual'
set logscale y
set format y "%.0e"
set grid

$PLOT

set terminal png
set output 'residual.png'
replot
EOF

マルチリージョンでは余計なものが表示されるので、少し修正がいる。

#!/bin/sh

VARS=`ls logs | grep FinalRes | sed -e 's/FinalRes_0//'`
if [ "$VARS" = "" ] ; then
    VARS=`ls logs | sed -e 's/_0//'`
fi

DIR=logs

PLOT=""
HEAD=1

for VAR in $VARS ; do
    if [ -e "logs/${VAR}_0" ] ; then
        V=`head -1 logs/${VAR}_0 | awk '{print $2}'`
        if [ $V != "region" ] ; then
            I=0
            for FILE in logs/${VAR}_* ; do
                if [ $HEAD -eq 1 ] ; then
                    PLOT="plot '$FILE' title '${VAR}_$I' w l"
                    HEAD=0
                else
                    PLOT="$PLOT, '$FILE' title '${VAR}_$I' w l"
                fi
                I=`expr $I + 1`
            done
        fi
    fi
done

gnuplot -p <<EOF
set terminal x11
set title 'Residuals'
set xlabel 'Time'
set ylabel 'Initial residual'
set logscale y
set format y "%.0e"
set grid

$PLOT

set terminal png
set output 'residual.png'
replot
EOF

また、輻射モデルに fvDOM を用いた場合は輻射モデルに関する残差が大量に表示されてしまうので、表示から外してしまった方が良い。

VARS=`ls logs | grep FinalRes | sed -e 's/FinalRes_0//' | grep -v ILambda`

実行権限を設定する。

$ chmod +x plot

つぎのように実行する。

$ ./plot

これは各変数の代数方程式の初期残差をプロットする。プロットを見て、残差が順調に下がっているかチェックする。もし残差が上下して落ち着かないようであれば、関係しそうな緩和係数を小さくしてみたり、境界条件などを見直したりしてみる。

上記のスクリプトの場合、非定常解析で各時間ステップにおいて反復計算を行うときは、各反復計算の最初の初期残差が表示される。各反復計算のすべての初期残差を foamLog の出力データからプロットするのは難しいので、つぎのようなスクリプトを用意する。

myFoamLog

#!/bin/sh

if [ $# -lt 1 ] ; then
    echo "usage: myFoamLog <log>"
    exit 0
fi


VARS="Ux Uy Uz T h"
#VARS="$VARS p p_rgh"
#VARS="$VARS k epsilon omega Rxx Rxy Rxz Ryy Ryz Rzz"

DIR=logs
mkdir -p $DIR

for VAR in $VARS ; do
    cat log | grep "Solving for $VAR" | grep -v "solution singularity" | sed s/,//g | awk '{print $8}' > $DIR/${VAR}_0
    SIZE=`wc $DIR/${VAR}_0 | awk '{print $1}'`
    if [ ! $SIZE -eq 0 ] ; then
        echo $VAR
    else
        rm $DIR/${VAR}_0
    fi
done

圧力や乱流統計量は、速度などと計算回数が一致しない可能性がある。

実行権限を設定する。

$ chmod +x myFoamLog

つぎのように実行する。

$ ./myFoamLog log

このスクリプトの出力データをプロットすれば、すべての反復計算の残差が表示される。

流量の確認

ソルバーのオプションを用いて、境界面の流量を計算することができる。

$ simpleFoam -postProcess -func 'flowRatePatch(name=outlet)' -latestTime

"-postProcess" は function object を実行するためのオプションである。"-func" は function object の関数を指定するためのオプションで、flowRatePatch は境界面 (パッチ) の流量を計算する関数である。"-latestTime" オプションは最後の結果のみ計算させるものである。計算には流束 phi が用いられている。phi は、非圧縮性流体ソルバーではセル界面の流速ベクトルと面積ベクトルの内積をとったもので、圧縮性流体ソルバーではそれに密度がかかる。それの総和をとることで体積流量か質量流量が計算される。これにより想定した流量が入っているかどうかをチェックできる。また、すべての入口・出口でそれぞれの流量を計算することで収支が合っているかどうかを見て、計算が十分に収束しているか確認できる。

計算中に流量を計算させたい場合は、system/controlDict で次のように設定する。

functions
{
    #includeFunc flowRatePatch(name=outlet);
}

ソルバーを実行すると、"postProcessing" ディレクトリの中にテキストデータが出力される。

計算結果をログに表示させたい場合はつぎのようにする。

functions
{
    #includeFunc flowRatePatch(name=outlet,log=true);
}

流量収支の計算

2 つの境界面の流量収支を計算するには、次のようにする。

functions
{
    massBalance
    {   
        type            fieldValueDelta;
        libs            ("libfieldFunctionObjects.so");
        writeControl    timeStep;
        writeInterval   1;  
        operation       add;

        region1
        {
            type        surfaceFieldValue;
            libs        ("libfieldFunctionObjects.so");
            operation   sum;
            fields      (phi);
            writeFields false;
            regionType  patch;
            name        inlet;
        }

        region2
        {
            type        surfaceFieldValue;
            libs        (fieldFunctionObjects);
            operation   sum;
            fields      (phi);
            writeFields false;
            regionType  patch;
            name        outlet;
        }
    }   
}

fieldValueDelta は 2 つの値に演算を施すためのものである。region1、region2 でそれぞれ surfaceFieldValue によって面の流束 phi の総和をとって流量を計算している (flowRatePatches の中身はこの surfaceFieldValue である)。ここでは境界面 (パッチ) inlet と outlet の流量収支を計算している。OpenFOAM では面の法線ベクトルは外側を向いており、その関係で流量は流入が負、流出が正になっている。そのため、2 つの差ではなく和をとっている (operation の add)。

上記の方法では 2 つの面の収支しかとれない。入口と出口が複数ある場合は、1 つの面にまとめる。OpenFOAM には計算メッシュのフェイスやセルをまとめるセットやゾーンというものがある。それらを編集するためのプログラムとして setSet がある。setSet ですべての境界面 (パッチ) をひとつにまとめるには、次のようにする。

$ setSet
readline>faceSet allPatches new patchToFace inlet
readline>faceSet allPatches add patchToFace outlet
...
readline>faceZoneSet allPacthes new setToFaceZone allPatches
readline>quit

最初に境界面 inlet により allPatches というフェイスセットを作り、それに outlet などを追加している。最後にフェイスセットからフェイスゾーンを作成している。

flowRateFaceZone を用いると、ゾーンの流量を計算できる。

$ simpleFoam -postProcess -func 'flowRateFaceZone(name=allPatches)'

これにより全境界面の収支が得られる。

バージョン 3.0.x 以前

バージョン 3.0.x 以前では、ユーティリティの patchIntegrate を用いる。

$ patchIntegrate -latestTime phi inlet

計算中に流量を計算させたい場合は system/controlDict で次のように設定する。

functions
{
    flowRate
    {
        type            faceSource;
        functionObjectLibs ("libfieldFunctionObjects.so");
        fields          (phi);
        source          patch;
        operation       sum;
        sourceName      outlet;
        valueOutput     false;
    }
}

熱量の確認

壁面の熱量は、計算結果に対して次のように計算させることができる。

$ buoyantSimpleFoam -postProcess -func wallHeatFlux -latestTime

ただし、圧縮性流体のケースにのみ対応する (buoyantBoussinesqSimpleFoam などでは使えない)。想定の熱量が入っているか、収支が合っているか確認できる。

計算中の熱量を得たい場合は、system/controlDict で次のようにする。

functions
{
    #includeFunc wallHeatFlux(writeControl=timeSt
}

ソルバーを実行すると、"postProcessing" ディレクトリの中にテキストデータが出力される。また、時刻ディレクトリにフィールドファイルが書き出される。

流量同様にして、熱量収支を計算することができる。

バージョン 3.0.x 以前

バージョン 3.0.x 以前では、ユーティリティの wallHeatFlux で壁面の熱量を計算させることができる。

$ wallHeatFlux -latestTime

ただし、constant/turbulenceProperties を要求するので、バージョン 2.4.x 以前なら定常解析の場合は仮に置いておけばよい。

y+ の確認

ソルバーのオプションを用いて、計算結果の y+ を計算することができる。

$ simpleFoam -postProcess -func yPlus -latestTime

ソルバーを実行すると、"postProcessing" ディレクトリの中にテキストデータが出力される。また、時刻ディレクトリにフィールドファイルが書き出される。y+ が想定の範囲に入っているか確認できる。

バージョン 3.0.x

バージョン 3.0.x では、ユーティリティの yPlus を用いる。

$ yPlus -latestTime

バージョン 2.x

バージョン 2.x 以前では、ユーティリティの yPlusRAS/yPlusLES を用いる。

$ yPlusRAS -latestTime

圧縮性流体のケースではオプション "-compressible" を付ける。

面平均値の確認

計算結果について物理量の面における平均値を確認するには、function object の patchAverage を用いる。

$ simpleFoam -postProcess -func 'patchAverage(name=outlet,U)' -latestTime

この場合は、postProcess ユーティリティを用いてもよい。

$ postProcess -func 'patchAverage(name=outlet,U)' -latestTime

ただし、常にソルバーを postProcess に置き換えられるわけではない。

計算中の結果が欲しい場合は、system/controlDict で次のようにする。

functions
{
    #includeFunc patchAverage(name=outlet,U)
}

ソルバーを実行すると、"postProcessing" ディレクトリの中にテキストデータが出力される。

バージョン 3.0.x 以前

バージョン 3.0.x 以前では、ユーティリティの patchAverage を用いる。

$ patchAverage -latestTime T outlet

体積平均値の計算

定常解析の場合、計算の収束性を見るために、物理量の体積平均値の推移もチェックしたほうがよい。物理量の体積平均値を得るために、function object をつぎのように設定する。

system/controlDict

functions
{
    #includeFunc mag(U,executeControl=timeStep)

    volAvgU
    {
        type            volFieldValue;
        libs            ("libfieldFunctionObjects.so");
        fields          (mag(U));
        writeFields     false;
        regionType      all;
        operation       volAverage;
        writeControl    timeStep;
        writeInterval   1;
    }
}

この場合は、ベクトルである U をスカラーに変換してから体積平均値を計算するようにしている。計算結果は "postProcessing" ディレクトリの中にテキストデータとして出力される。この計算は計算時に行うほうがよいだろう。

マルチリージョンのケースでは、"region" によるリージョンが必要である。

バージョン 4.x

バージョン 4.x では、以下のようにする。

system/controlDict

functions
{
    #includeFunc mag(U,executeControl=timeStep)

    volAvgU
    {
        type            volRegion;
        libs            ("libfieldFunctionObjects.so");
        fields          (mag(U));
        writeFields     false;
        regionType      all;
        operation       volAverage;
        wirteControl    timeStep;
        writeInterval   1;
    }
}

バージョン 3.0.x 以前

バージョン 3.0.x 以前では、以下のようにする。

system/controlDict

functions
{
    magU
    {
        type            calcMag;
        functionObjectLibs ("libFVFunctionObjects.so");
        fieldName       U;
        resultName      magU;
        outputControl   outputTime;
        outputInteval   1;
    }

    volAvgU
    {
        type            cellSource;
        functionObjectLibs ("libfieldFunctionObjects.so");
        fields          (magU);
        valueOutput     false;
        source          all;
        operation       volAverage;
        outputControl   timeStep;
        outputInterval  1;
    }
}

計算結果の時間平均化

非定常解析の計算結果を時間平均化する必要がある場合は、system/controlDict で以下のように設定する。

system/controlDict

functions
{
    fieldAverage
    {
        type            fieldAverage;
        libs            ("libfieldFunctionObjects.so");
        fields
        (
            U
            {
                mean            on;
                prime2Mean      on;
                base            time;
            }

            p
            {
                mean            on;
                prime2Mean      on;
                base            time;
            }
        );
        writeControl    writeTime;
        writeInterval   1;
    }
}

ソルバーの "-postProcess" オプションで function object を実行する。

$ pimpleFoam -postProcess

フィールドデータとして "UMean"、"pMean" などが出力される。

上の例では計算後に処理しているが、計算前に設定しておけば、計算時に function object が実行され、平均値が出力される。

バージョン 3.0.x 以前

バージョン 3.0.x 以前では、以下のようにする。

functions
{
    fieldAverage
    {
        type            fieldAverage;
        functionObjectLibs ("libfieldFunctionObjects.so");
        fields
        (
            U
            {
                mean            on;
                prime2Mean      on;
                base            time;
            }

            p
            {
                mean            on;
                prime2Mean      on;
                base            time;
            }
        );
        outputControl   outputTime;
        outputInterval  1;
    }
}

execFlowFunctionObjects で function object を実行する。

$ execFlowFunctionObjects

せん断応力の計算

壁面のせん断応力は、計算結果に対して次のように計算させることができる。

$ simpleFoam -postProcess -func wallShearStress -latestTime

ソルバーを実行すると、"postProcessing" ディレクトリの中にテキストデータが出力される。また、時刻ディレクトリにフィールドファイルが書き出される。

バージョン 3.0.x 以前

バージョン 3.0.x 以前では、ユーティリティの wallShearStress で壁面の熱量を計算させることができる。

$ wallShareStress -latestTime

圧力損失の計算

圧力損失を計算するには、全圧の差をとればよい。全圧については、function object のtotalPressureIncompressible/totalPressureCompressible を用いる。差をとるには、流量収支のところで用いた fieldValueDelta で operation を subtract にする。

functions
{
    #includeFunc totalPressureIncompressible(rhoInf=1.3,executeControl=timeStep)

    pressureLoss
    {
        type            fieldValueDelta;
        libs            ("libfieldFunctionObjects.so");
        writeControl    timeStep;
        writeInterval   1;
        operation       subtract;

        region1
        {
            type        surfaceFieldValue;
            libs        ("libfieldFunctionObjects.so");
            operation   areaAverage;
            fields      (total(p));
            writeFields false;
            regionType  patch;
            name        inlet;
        }

        region2
        {
            type        surfaceFieldValue;
            libs        (fieldFunctionObjects);
            operation   areaAverage;
            fields      (total(p));
            writeFields false;
            regionType  patch;
            name        outlet;
        }
    }
}

totalPressureIncompressible の場合は、rhoInf で密度を指定する必要がある。上の例では、境界面 inlet と outlet の間で圧力損失を計算している。

もし、境界ではない面から圧力損失を求めたい場合は、たとえばつぎのようにする。

functions
{
    #includeFunc totalPressureIncompressible(rhoInf=1.3,executeControl=timeStep)

    pressureLoss
    {   
        type            fieldValueDelta;
        libs            ("libfieldFunctionObjects.so");
        writeControl    timeStep;
        writeInterval   1;  
        operation       subtract;

        region1
        {
            type        surfaceFieldValue;
            libs        ("libfieldFunctionObjects.so");
            operation   areaAverage;
            fields      (total(p));
            writeFields false;
            regionType  sampledSurface;
            name        x=0.1m;
            sampledSurfaceDict
            {
                type         plane;
                planeType    pointAndNormal;
                pointAndNormalDict
                {
                    point    (0.1 0 0); 
                    normal   (1 0 0); 
                }
            }
        }

        region2
        {
            type        surfaceFieldValue;
            libs        (fieldFunctionObjects);
            operation   areaAverage;
            fields      (total(p));
            writeFields false;
            regionType  patch;
            name        outlet;
        }
    }
}

上の例では、x = 0.1 m の断面と outlet で全圧差を計算している。

残差などのモニタリング

バージョン 2.4.0 からは、foamMonitor により残差など function object から出力されたデータのモニタリングが可能である。たとえば、残差と流速の体積平均値をモニターするとする。

※OpenCFD 版 v1906 以降は residuals の代わりに solverInfo を用いる。

system/controlDict

functions
{
    #includeFunc residuals
    #includeFunc mag(U,executeControl=timeStep)

    volAvgU
    {
        type            volFieldValue;
        libs            ("libfieldFunctionObjects.so");
        fields          (mag(U));
        writeFields     false;
        regionType      all;
        operation       volAverage;
        writeControl    timeStep;
        writeInterval   1;
    }
}

残差をモニターするには、計算中につぎのように実行する。

$ foamMonitor -r 1 -l postProcessing/residuals/0/residuals.dat &

流速の体積平均値の場合は、つぎのように実行する。

$ foamMonitor -r 1 postProcessing/volAvgU/0/cellSource.dat &

計算実行時に自動的に実行されるようにするとよいだろう。つぎのようなスクリプトを用意しておくとよいかもしれない。

run

#!/bin/sh

rm -rf postProcessing/residuals
rm -rf postProcessing/volAvgU

. $WM_PROJECT_DIR/bin/tools/RunFunctions
SOLVER=`getApplication`

foamJob $SOLVER

sleep 1

TIME=`cat log | awk '/Create mesh for time = /{print $6; exit}'`
FILE_RESIDUALS="postProcessing/residuals/$TIME/residuals.dat"
FILE_AVG_U="postProcessing/volAvgU/$TIME/volRegion.dat"

foamMonitor -r 1 -i 5 -l $FILE_RESIDUALS &
foamMonitor -r 1 -i 5 $FILE_AVG_U &

xterm -e "tail -f log" &

バージョン 4.x

バージョン 4.x では、以下のようにする。

functions
{
    #includeFunc residuals
    #includeFunc mag(U,executeControl=timeStep)

    volAvgU
    {
        type            volRegion;
        libs            ("libfieldFunctionObjects.so");
        fields          (mag(U));
        writeFields     false;
        regionType      all;
        operation       volAverage;
        wirteControl    timeStep;
        writeInterval   1;
    }
}

バージョン 3.0.x 以前

バージョン 3.0.x 以前では、以下のようにする。

system/controlDict

functions
{
    residuals
    {
        type            residuals;
        functionObjectLibs ("libutilityFunctionObjects.so");
        fields          (U p);
    }

    magU
    {
        type            calcMag;
        functionObjectLibs ("libFVFunctionObjects.so");
        fieldName       U;
        resultName      magU;
        outputControl   outputTime;
        outputInteval   1;
    }

    volAvgU
    {
        type            cellSource;
        functionObjectLibs ("libfieldFunctionObjects.so");
        fields          (magU);
        valueOutput     false;
        source          all;
        operation       volAverage;
        outputControl   timeStep;
        outputInterval  1;
    }
}

計算結果の確認と処理

計算結果の詳細な確認および処理は ParaView で行う。ケースディレクトリで paraFoam を実行すると、ParaView が起動して計算結果が読み込まれる。

$ paraFoam

計算結果の処理の前に、計算結果が物理的に妥当かどうか確認する。

並列計算の結果を処理する場合は、あらかじめ reconstructPar を実行しておく必要がある。

マルチリージョンのケースでは、次のように領域ごとに実行する。

$ paraFoam -region fluid -touch
$ paraFoam -region solid -touch

領域ごとに "*.OpenFOAM" ("*" にはケース名などが入る)というファイルができるので、それらを paraFoam ではなく ParaView を起動して読み込む。

paraFoam 自体は、"*.OpenFOAM" ファイル (中身は空でよい)を作成して ParaView で読み込んでいる。この場合、OpenFOAM が用意している OpenFOAM ケースリーダーが使われる。この方法とは別に、"*.foam" という空ファイルを用意して読み込む方法がある。この場合は、ParaView にはじめから用意されている OpenFOAM ケースリーダーが使われる。こちらの場合は、並列計算結果を結合 (reconstructPar) しなくても結果を読み込める特徴がある。ただし、使っている OpenFOAM のバージョンを完全にはサポートしていない可能性があり得る。

フォーマットの変換

計算結果ファイルの ascii/binary の変換や compressed/uncompressed の変換を行いたい場合は、system/controlDict を望みのフォーマットに設定したあと、foamFormatConvert を実行する。

$ foamFormatConvert

このユーティリティは、結果を読み込み、system/controlDict の設定に従って結果を書き出す。

ステップ数のカウント

非定常計算で計算ステップ数を数えるには、"^Time =" を数えればよい。以下のようなスクリプトを作っておけばよいかもしれない。

count_steps

#!/bin/sh

if [ $# -lt 1 ] ; then
    echo "count_steps <log>"
    exit 0
fi

cat $1 | grep "^Time =" | awk 'BEGIN{i=1} {print i, $3; i++}'
cat $1 | grep "^Time =" | wc | awk '{print $1}'

ログファイルを指定する。

$ ./count_steps log