PyFoam メモ

2013年9月21日

はじめに

PyFoam は、OpenFOAM をもう少し使いやすくするための Python モジュールおよびツール群である。以下では PyFoam の使い方について簡単にメモする。

バージョン

OpenFOAM 2.2.1, PyFoam 0.6.1

インストール

ここ に従って svn でソースコードを入手。

$ svn co https://svn.code.sf.net/p/openfoam-extend/svn/trunk/Breeder/other/scripting/PyFoam/

あるいは上記ページのリンク ("Downloads" の "Current Version") からパッケージをダウンロードできる。

インストール。

$ cd PyFoam
$ mkdir ~/OpenFOAM/PyFoam
$ python setup.py install --prefix=~/OpenFOAM/PyFoam

以下を ~/.bashrc に追加。

export PYTHONPATH=~/OpenFOAM/PyFoam/lib/python2.7/site-packages:$PYTHONPATH
export PATH=~/OpenFOAM/PyFoam/bin:$PATH

上記の "python2.7" の部分は Python のバージョンによって変わる。

Gnuplot と Python の Numpy モジュールもインストールしておく。

~/.bashrc を読み込む。

$ . ~/.bashrc

テスト

以下のコマンドを実行。

$ pyFoamVersion.py

OpenFOAM と PyFoam のバージョンが表示されれば OK。

また、python を立ち上げ、以下のように打ち込む。

$ python
>>> import PyFoam
>>> import PyFoam.FoamInformation
>>> print PyFoam.FoamInformation.foamTutorials()

OpenFOAM のチュートリアルのパスが表示されれば OK。

ツール

pyFoamPlotRunner.py

これを使って OpenFOAM のソルバーを実行すると、商用 CFD ソフトで見るような、残差などのグラフが表示される。

たとえば、ケースディレクトリ内で icoFoam を実行する場合は、次のようにする。

$ pyFoamPlotRunner.py icoFoam

グラフのために以下のようなオプションが使える。

  • --no-default : 何も表示しない
  • --with-iterations : 線形ソルバーの反復回数を表示
  • --with-courant : クーラン数を表示
  • --with-deltat : 時間刻み幅を表示
  • --with-all : 表示できるものすべてを表示

あとでグラフを見るには次のようにする。

$ pyFoamPlotWatcher.py PyFoamRunner.icoFoam.logfile

ログファイル (ソルバーの標準出力) を指定する。上のオプションが使える。また、つぎのオプションが使える。

  • --start=START : 表示開始時刻の指定
  • --end=END : 表示終了時刻の指定

並列計算を行う場合は、次のようにする。

$ pyFoamPlotRunner.py --procnr=2 icoFoam

--procnr で CPU 数を指定する。--autosense-parallel オプションで並列数を自動で決めるさせることもできる。

以下のようなオプションもある。

  • --restart : 続きから計算する
  • --progress : 出力を時刻だけにする
  • --no-log : ログファイルを出力しない
  • --report-usage : 計算の最後に最大使用メモリ量を表示する

pyFoamCaseReport.py

ケースの情報を表示する。ヘルプを見るには、以下のようにする。

$ pyFoamCaseReport.py -h

たとえば、以下のようにすれば境界条件の情報が表示される。

$ pyFoamCaseReport.py --short-bc-report cavity

また、セル数などの情報は、次のようにして得られる。

$ pyFoamCaseReport.py --case-size cavity

pyFoamChangeBoundaryType.py

ケースの const/polyMesh/boundary の境界のタイプを変更できる。

$ pyFoamChangeBoundaryType.py cavity movingWall patch

pyFoamClearBoundaryValue.py

フィールドの境界条件の "value" の値を変更できる。

$ pyFoamClearBoundaryValue.py --value="(2 0 0)" cavity/0/U movingWall

"value" 以外の値を変更したい場合はつぎのようにする。

$ pyFoamClearBoundaryValue.py --destination-key="inletValue" --value=1 0/alpha outlet

pyFoamClearCase.py

計算結果を削除する。改めて計算を実行しなおす場合などに使える。

$ pyFoamClearCase.py cavity

次のようにすると、並列計算用の processor* ディレクトリも一緒に削除する。

$ pyFoamClearCase.py --processors-remove cavity

最後の結果を残したい場合はつぎのようにする。

$ pyFoamClearCase.py --keep-last cavity

ただし、processor* 内のデータは削除される。並列計算の結果を残したい場合は、上を実行する前に reconstructPar を実行する。

ある時間よりあとのデータだけを消したい場合はつぎのようにする。

$ pyFoamClearCase.py cavity --after=0.042

この場合、0.042 秒よりあとのデータが削除される (0.042 のディレクトリまで残る)。

pyFoamClearInternalField.py

フィールドの internalField の値を設定できる。

$ pyFoamClearInternalField.py --value="(2 0 0)" cavity/0/U

pyFoamCloneCase.py

ケースのクローンを作る。計算結果はコピーされない。

$ pyFoamCloneCase.py cavity cavity2

pyFoamCopyLastToFirst.py

ケースの最終結果を、別のケースの初期値に設定する。

$ pyFoamCopyLastToFirst.py cavity cavity2

pyFoamCreateBoundaryPatches.py

const/polyMesh/boundary の境界をフィールドファイルに追加する。

$ pyFoamCreateBoundaryPatches.py --verbose --overwrite --clear-unused cavity/0/U

--overwrite は上書き指定、--clear-unused で使われない境界情報を削除する。つまり、よそのケースから持ってきたフィールドファイルを本ケース用に作り替える。

pyFoamDecompose.py

パラレル計算用にメッシュを分解する。

$ pyFoamDecompose.py --method=simple --n="2,1,1" --delta=1e-4 cavity 2

オプションは decomposeParDict で指定するパラメタ、最後の数字が CPU 数。decomposeParDict の用意と decomposePar の実行を勝手にやってくれる。

pyFoamListCases.py

カレントディレクトリにあるケースのリストを表示する。

pyFoamPackCase.py

ケースの計算に必要なファイルだけを tar でまとめる。

$ pyFoamPackCase.py cavity

"cavity.tgz" ができる。計算結果は含まない。

pyFoamReadDictionary.py

辞書のキーワードの値を表示する。

$ pyFoamReadDictionary.py cavity/system/controlDict deltaT

controlDict の deltaT の値が表示される。

キーワードが入れ子になっている場合は、次のようにする。

$ pyFoamReadDictionary.py cavity/system/fvSolution "PISO['nCorrectors']"

pyFoamWriteDictionary.py

辞書のキーワードの値を変更する。

$ pyFoamWriteDictionary.py cavity/system/controlDict deltaT 0.1

controlDict の deltaT の値が 0.1 に設定される。

キーワードが入れ子になっている場合は、次のようにする。

$ pyFoamWriteDictionary.py cavity/system/fvSolution "PISO['nCorrectors']" 3

フィールドの境界条件のタイプを設定することもできる。

$ pyFoamWriteDictionary.py 0/U 'boundaryField["wall"]["type"]' slip

Python から使う

PyFoam は Python モジュールであるから、Python から使ってこそ本領を発揮できるといえる。以下では PyFoam モジュールの簡単な利用例を示す。

メッシュの境界を表示する例

showBoundaries.py

import sys
from os import path
from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile

if len(sys.argv) < 2:
	print "usage: showBoundaries.py <case>"
	sys.exit(0)

case = sys.argv[1]

try:
	boundary = ParsedParameterFile(
	  path.join(case, "constant", "polyMesh", "boundary"),
	  boundaryDict=True)
except IOError, e:
	print "error: ", e
	sys.exit(-1)

boundaries = boundary.content

print "Case: ", case
print

name = True
for b in boundaries:
	if name:
		print "Name: ", b
		name = False
	else:
		print "Type: ", b["type"]
		print
		name = True

PyFoam の ParsedParameterFile を使って辞書の情報を得ている。それを使うための準備が以下の行。

from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile

辞書の情報を得ているのが以下の部分。

boundary = ParsedParameterFile(
	  path.join(case, "constant", "polyMesh", "boundary"),
	  boundaryDict=True)

ここではケースの constant/polyMesh/boundary の情報を得ている。以下で辞書の中身を得る。

boundaries = boundary.content

boundaries の要素は境界の名前と Python の辞書型データからなり、辞書型データで b["type"] などとすると、それに対応した OpenFOAM の辞書のキーワードの値にアクセスできる。

フィールドの境界を表示する例

showFieldBoundaries.py

import sys
from os import path
from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile

if len(sys.argv) < 3:
	print "usage: showFieldBoundaries.py <case> <field>"
	sys.exit(0)

case = sys.argv[1]
field = sys.argv[2]

try:
	boundary = ParsedParameterFile(path.join(case, "0", field))
except IOError, e:
	print "error: ", e
	sys.exit(-1)

boundaries = boundary["boundaryField"]

print "Case: ", case
print

for b in boundaries:
	print "Name: ", b
	print "Type: ", boundaries[b]["type"]
	if boundaries[b].has_key("value"):
		print "Value: ", boundaries[b]["value"]
	print

はじめの constant/polyMesh/boundary にアクセスする例よりちょっぴり簡単になっている。ParsedParameterFile で ケースの 0 にあるフィールドデータを取得し、Python の辞書型データから情報を取り出している。

フィールドに境界を追加する例

addFieldBoundary.py

import sys
from os import path
from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile

if len(sys.argv) < 6:
	print "usage: addFieldBoundary.py <case> <field> <name> <type> <value>"
	sys.exit(0)

case = sys.argv[1]
field = sys.argv[2]
name = sys.argv[3]
type = sys.argv[4]
value = sys.argv[5]

try:
	boundary = ParsedParameterFile(path.join(case, "0", field))
except IOError, e:
	print "error: ", e
	sys.exit(-1)

boundaries = boundary["boundaryField"]

print "Case: " + case
print
print "Add boundary:"
print "Name: " + name
print "Type: " + type
if value != "":
	print "Value: " + value

b = {}
b["type"] = type
if value != "":
	b["value"] = "uniform " + value
boundaries[name] = b

boundary.writeFile()

print "Done."

取得した辞書情報は、取り出すばかりではなく、情報を設定することもできる。最後の boundary.writeFile() で、変更した内容をファイルに書き出している。上は境界を追加する例として示してはいるが、既存の境界を指定すれば情報を変更することができる。