Python による blockMeshDict の生成

2022年7月24日

はじめに

Python による blockMeshDict の生成について。

使用バージョン

OpenFOAM v2112

Python による blockMeshDict の生成 (blockMeshPython)

いちいち blockMeshDict を作成するのは手間なので、blockMeshDict の作成を簡易化する Python モジュールを作成してみた。

ファイル

変更点

20210411

  • 箱をグリッド状に扱う仕組みを追加。
  • 建物モデルの例を追加。

example.py

#!/usr/bin/python
from blockMesh import *

setScale(1)

bl1, ps1, ls1, bs1 = createBox(0, 0, 0, 1, 1, 0.1, 20, 20, 1)
bl2, ps2, ls2, bs2 = createBox(1, 0, 0, 1, 1, 0.1, 20, 20, 1)

changeLineType(ls1[0], 'spline', ((0.3, 0.2, 0), (0.7, 0, 0)))
changeLineType(ls1[4], 'spline', ((0.3, 0.2, 0.1), (0.7, 0, 0.1)))

setBlockGrading(bl1, 'edge', (2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 1, 1))

mergeBoundary(bs1[1], bs2[0])

addGroup('left',   'patch', (bs1[0]))
addGroup('right',  'patch', (bs2[1]))
addGroup('top',    'wall',  (bs1[2], bs2[2]))
addGroup('bottom', 'wall',  (bs1[3], bs2[3]))
addGroup('front',  'empty', (bs1[4], bs2[4]))
addGroup('back',   'empty', (bs1[5], bs2[5]))

write('system')
run('.')

まず、blockMesh モジュールをインポートする。

from blockMesh import *

setScale() でスケールを指定する。

setScale(1)

デフォルトは 1 なので、この場合は指定しなくてもよい。

createBox() で箱を作る。

bl1, ps1, ls1, bs1 = createBox(0, 0, 0, 1, 1, 0.1, 20, 20, 1)
bl2, ps2, ls2, bs2 = createBox(1, 0, 0, 1, 1, 0.1, 20, 20, 1)

引数は、箱の開始点 x0, y0, z0 と箱の幅 dx, dy, dz、分割数 nx, ny nz である。返り値はそれぞれブロック (箱の実体のこと) の番号、点、辺、境界の番号のタプルである。番号は下図の順番で入っている。

本スクリプトでは 2 次元を基本としているため、XY 平面を見た状態を考えており、手前 (Z 軸正方向) を面 4 として、境界には面 0, 1, ..., 7 に対して順番に "left", "right", "top", "bottom", "front", "back" という名前が付けられている (実際にはこれに箱の番号が付く)。

changeLineType() で辺の形状を設定する。

changeLineType(ls1[0], 'spline', ((0.3, 0.2, 0), (0.7, 0, 0)))
changeLineType(ls1[4], 'spline', ((0.3, 0.2, 0.1), (0.7, 0, 0.1)))

setBlockGrading() で辺の分割の拡大率を設定する。

setBlockGrading(bl1, 'edge', (2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 1, 1))

パラメータは blockMesh と共通なので、第 3 引数の辺の順番は X 方向、Y 方向、Z 方向の順になっている。上の図の辺番号でいえば、(0, 2, 6, 4, 3, 1, 5, 7, 8, 9, 10, 11) の順である。

mergeBoundary() でマージする面の対を指定する。

mergeBoundary(bs1[1], bs2[0])

ここではひとつめの箱の右側面とふたつめの箱の左側面を結合させている。

addGroup() で境界グループを追加する。

addGroup('left',   'patch', (bs1[0]))
addGroup('right',  'patch', (bs2[1]))
addGroup('top',    'wall',  (bs1[2], bs2[2]))
addGroup('bottom', 'wall',  (bs1[3], bs2[3]))
addGroup('front',  'empty', (bs1[4], bs2[4]))
addGroup('back',   'empty', (bs1[5], bs2[5]))

境界をまとめて名前をつけている。境界グループは境界として出力される。境界もまた境界として出力されるが、境界が境界グループに属する場合は、境界グループのほうが優先される。上の記述では、createBox() によってつけられた境界名をつけなおしている。

write() で出力するディレクトリのパスを指定して blockMeshDict を書き出す。

write('constant/polyMesh')

run() でケースディレクトリのパスを指定して blockMesh を実行する。

run('.')

このスクリプトをケースディレクトリ内で実行すると、blockMesh によりメッシュが作成される。

境界の設定

changeBoundaryName(), changeBoundaryType() で境界の名前やタイプを設定できる。上の例で結合した面を、代わりに cyclic でくっつけるにはつぎのようにする。

changeBoundaryName(bs1[1], 'cyclic_master')
changeBoundaryType(bs1[1], 'cyclic', 'cyclic_slave')
changeBoundaryName(bs2[0], 'cyclic_slave')
changeBoundaryType(bs2[0], 'cyclic', 'cyclic_master')

また、境界グループでも同様のことができる。

addGroup('cyclic_master', 'cyclic', (bs1[1]), 'cyclic_slave')
addGroup('cyclic_slave',  'cyclic', (bs2[0]), 'cyclic_master')

cylinder.py

cylinder.py は、円筒 (2 次元で考えると円だが) 周りのメッシュの生成の例である。

点を移動する setPoint() 関数を用いている。

setPoint(ps1[0], -d, d, z0)
setPoint(ps1[4], -d, d, z1)

setPoint() は、点を指定した座標に移動する。とりあえず箱を作って、点を円筒上に移動している。ちなみに、移動距離を指定して点を移動する movePoint() という関数もある。

movePoint(id, dx, dy, dz)

円筒は 'arc' で表す。

changeLineType(ls1[0], 'arc', (0, r, z0))

building.py

building.py は、建物モデルのメッシュの例である。

これは、箱をグリッド状に配置するものとして扱う grid モジュールを用いている。

grid = createGrid(2, 3, 3)

グリッドは、XY 面上に行列状に並んでいるものが、Z 軸方向に層をなしていると考えている。上の例では、XY 面上に 3 x 3 で並んだものが Z 軸方向に 2 つあるということである。gird の要素は空 (None) なので、これに箱を入れる必要がある。

    grid[i][0][0] = createBox(x0, y0, z, x_up, y_pad, dz, nx_up, ny_pad, nz2)
    grid[i][0][1] = createBox(x1, y0, z, d, y_pad, dz, nx, ny_pad, nz2)
    grid[i][0][2] = createBox(x2, y0, z, x_down, y_pad, dz, nx_down, ny_pad, nz2)

上のコードは、層 i の 0 列の 3 つに箱を設定している。上の図でいうと、手前から X 軸方向 (右斜め上方向) 奥に向かっての 3 つの領域である。

グリッドからブロックだけ取り出すには、getGridBlock() を使う。

block = getGridBlock(grid)

また、境界だけ取り出すには、getGridBoundary() を使う。

boundary = getGridBoundary(grid)

内部面のマージは、mergeGridBoundary() を呼び出すだけでよい。

mergeGridBoundary(boundary)

getGridPatch() でグリッドの側面の境界面を得られるので、これを用いて境界条件を設定できる。

patch = getGridPatch(boundary)
addGroup('inlet',  'patch', patch[0])
addGroup('outlet', 'patch', patch[1])
addGroup('back',   'wall',  patch[2])
addGroup('front',  'wall',  patch[3])
addGroup('top',    'wall',  patch[4])
addGroup('ground', 'wall',  patch[5])

側面の順番は、箱の場合と同じである。

グループ化されていない境界 (この例では建物の境界) をまとめてグループ化するには、次のようにする。

patch = getUngroupedBoundary()
addGroup('walls', 'wall', patch)

ゾーンの設定

setBlockZone() でブロックにゾーンを設定することができる。

setBlockZone((id1, id2, ...), name)