使用環境
- Ubuntu 16.04
- OpenFOAM 3.0.1
- OpenFOAM 4.1
概要
OpenFOAMではcontrolDictのfunctions機能を使うことで平均値・合計値などを任意の時間ステップで出力できる。
しかしオリジナルソルバーのデバッグ中などでは、より詳細に値を出力したい場合もある。
OpenFOAMの関数だけを用いて任意のファイル・値・形式を出力する方法をまとめた。
作成したヘッダファイル(一例)
以下の二つのヘッダファイルを作成した。
- outputInitial.H
- output.H
タイムループ前にoutputInitial.H
でファイルを準備し、タイムループ毎にoutput.H
をincludeしてファイルに書き込む
例1:laplacianFoamで最大/平均/最小温度をtxtファイルに出力する
簡単な例を交えて説明する。
ここでは温度の最大値・平均値・最小値をgnuplot向けに出力していく例を考える。
下みたいになることが目標。
# time max mean min
1 273 273 273
2 273.21614 273.001560 272.816514
3 273.41561 273.002146 272.745651
4 273.64815 273.003184 272.647846
...
- 項目間がtab区切り
- 1行目は#で始まる
という形式だとgnuplotでプロットできる。
作成したファイルの中身は以下の通り。
const fileName dPath = "postProcessing"; // postProcessingディレクトリを指定する
if(!isDir(dPath)) mkDir(dPath); // ディレクトリ作成の関数もOFに備わっている
const fileName fPath = dPath / "temperature.txt"; // fileName型の"/"演算子で文字列"postProcessing/temperature.txt"を生成
OFstream os(fPath); // ここに出力していく
os << "#time" << tab << "max" << tab << "mean" << tab << "min" << endl; // 一行目を#で始めるとgnuplotで読み込める
//volScalarField T // volScalarField型の温度Tについて考える
const word t = runTime.timeName(); // 時刻は.timeName()でword{aka string}型、.value()でscalar{aka double}型
os << t << tab << gMax(T) << tab << gAverage(T) << tab << gMin(T) << endl; // tabでタブ、nlかendlで改行ができる
普通のファイル操作よりも簡単にできる。
ケースディレクトリがカレントになる。
これを例えば以下のようにincludeすればファイルに値が書き込まれていく。
...
int main(int argc, char *argv[])
{
....
#include "outputInitial.H" // タイムループの前に呼び出し
while (simple.loop())
{
...
#include "output.H" // 計算後に呼び出し
}
...
return 0;
}
例2:pimpleFoamでpatch毎のcsvファイルに平均圧力と質量流量をそれぞれ出力する
この例ではあまり需要がないかもしれないが、patch毎、phase毎、region毎などでファイルを分けたい場合があるかもしれない。
こういう場合はOFstreamのPtrListを作成すると操作しやすい。
... // ディレクトリ作成
PtrList<OFstream> os(mesh.boundary().size()); // ファイル数(patchの数)を指定する
forAll(mesh.boundary(), patchI) { // ここのpatchI(int型)がファイル番号に対応する
const fvPatch& patch = mesh.boundary()[patchI];
const fileName fPath = dPath / patch.name() + ".csv"; // patch名をファイル名にする
os.set(
patchI, // patchI番目にOFstreamを生成
new OFstream(fPath)
);
os[patchI] << "#time" << tab << "pressure(Pa)" << tab << "massFlow(kg/s)" << endl; // 単位もつけてみた
}
//volScalarField p 絶対圧[Pa]
//surfaceScalarField phi 質量流量[kg/s]
const word t = runTime.timeName();
forAll(mesh.boundary(), patchI) {
const scalarField& pp = p.boundaryField()[patchI]; // patch毎の値を取り出す。fvPatchScalarFieldでも可。
const scalarField& pphi = phi.boundaryField()[patchI]; // patch毎の値を取り出す。fvsPatchScalarFieldでも可。
os[patchI] << t << tab << gAverage(pp) << tab << gSum(pphi) << endl;
}
これで以下のようにwall.csv、inlet.csv、outlet.csvが生成された。
# time pressure(Pa) massFlow(kg/s)
0.001 100000 0
0.002 100012.142 0
0.003 100031.344 0
0.004 100051.242 0
...
# time pressure(Pa) massFlow(kg/s)
0.001 100000 0
0.002 100034.161 0.221643
0.003 100058.015 0.351941
0.004 100075.169 0.461891
...
# time pressure(Pa) massFlow(kg/s)
0.001 100000 0
0.002 100000 -0.216546
0.003 100000 -0.348641
0.004 100000 -0.456116
...