OpenFOAMのチュートリアル改変2 - blockMeshDictの編集


前提

  • VirtualBoxとDEXCSを使ってOpenFOAMを実行していること。(それ以外の環境でも、多少読み替えれば以下を理解できなくもないが、初心者にはお勧めしない。それよりも、自分と同じ環境の人が作った解説ページを探すか、あるいはVirtualBoxとDEXCSを使ってOpenFOAMをインストールしなおすのがよいと思う。)
  • 別ページの「OpenFOAMのチュートリアル実施」を読んだか、またはOpenFOAMのチュートリアルの実行の仕方が分かること。

まずはチュートリアルをそのまま実施

チュートリアルの「pitzDaily」を例に説明する。pitzDailyにはいくつかのバージョンがあるが、今回はpisoFoamという解法のものを例に説明する。

このチュートリアルには「Allrun」ファイルが無いので、各コマンドを手動で入れる必要がある。といっても、このチュートリアルの場合は「blockMesh」と「pisoFoam」の2コマンドを実行するだけでよい。

以下の命令は、(1) チュートリアルからpitzDailyフォルダをコピーし、(2) コピーしたpitzDailyフォルダの中に入り、(3) blockMeshを実行し、(4) pisoFoamを実行し、(5) 結果を表示する、というもの。ただしpisoFoamを単純に実行すると、ログの表示時間が馬鹿にならないので、grepで部分的に表示させている。この行を単に「pisoFoam」としても(「|grep」から行末まで消す)、時間はかかるが同じ結果が得られる。

チュートリアルpitzDailyをそのまま実施
run
cp -r $FOAM_TUTORIALS/incompressible/pisoFoam/LES/pitzDaily .
cd pitzDaily
blockMesh
pisoFoam |grep -E 'Time\s=\s[0-9]*\.[0-9]\s'
paraFoam

paraViewの画面になってから、Play(再生)ボタンを押すと、結果がアニメーション表示される。

左上から流入し、右側から流出する。その際、左下に角があるため、この個所に吹き溜まり生じ、途中に渦ができる様子がシミュレーションされる。

確認出来たら、一度paraViewを終了する。つまり、paraView画面右上のクローズボタン(赤い×ボタン)をクリックする。)

流路形状の構造の説明

流路はブロックからできている

blockMeshを使う場合、全ての領域は、点8個から成る四角いブロックから構成されている。このチュートリアルの流路は、5つのブロックからできている。

上の図を見て分かるように、ブロック同士は面全体で結合している。なお、この図は、見やすくするため、オリジナルよりも厚さを増やしている。

オリジナルのブロック構成は次のようになっている。

オリジナルの青ブロックの上に、もう一つブロックを乗せたいとする。この場合、次の図のようにブロックを足すことはできない、

追加した茶色いブロックと、元からある青いブロックが、全面では接触していない(青いブロックの右半分のみと接触している)ためである。この形で解析をしたい場合には、元からあるブロックも分割して、例えば、次の図のようにする必要がある。

この修正には時間がかかるので、今回は簡単に、次の図のように改造することにする。

以下でこの改造方法を理解すれば、もう一つ上の分割も、手間はかかるが、同様に実行することができるようになる。

改造の前に、オリジナルのブロックがどのように構成されているか説明する。まずは上の図の黄色いブロックについてのみ説明する。

点の定義

ブロックの構成は「system/blockMeshDict」というファイルで定義されている。まずは次のコマンドで、これを開いて見る。

blockMeshDictの編集
xdg-open system/blockMeshDict

すると、次のようなファイルが開く。(ただし行末で「// 0」のように書かれている箇所は、私が書き足した注釈です。)

19行目の「vertices」で定義されているのが、頂点である。行の上の方から点0、点1...となっており、最後が点21である。以下、この点の番号で、図形を定義することになる。点の番号は、(1ではなく)0から始まることに注意。番号は自動で付与されるので、以下で立体形状を定義した後に、気が変わってverticesの途中の行を削除すると、立体形状の定義を全部書き換える必要がある。

立体と分割の定義

立体の定義では、まずはブロックを定義する。このチュートリアルの黄色(右下)のブロックは、次のように構成されている。

つまり、点5, 6, 8, 9, 16, 17, 19, 20の8点で構成されている。このブロックの定義は、先ほどのblockMeshDictファイルの「blocks」の箇所に書かれている。

ブロックの順番に縛りは無いが、このブロックにも0から始まる番号が自動付与され、エラーメッセージが出た場合にはその番号が表示される。

黄色のブロックは、下から2つめのhex、つまり、

hex (5 8 9 6 16 19 20 17)
(25 27 1)
simpleGrading (2.5 1 1)

の3行である。最初の行は、8つの点を並べたものであるが、並べ方にルールがある。ブロックの向かい合った面を1組選び、その1つの面の点を反時計周りにつなげる。例えば黄色のブロックの場合、奥の面と手前の面を選び、奥の面を構成する4点(5, 6, 8, 9)を反時計回りに並べる。例えば次の図の緑の矢印の順につなげる。

上の図の例では、(5 8 9 6)である。どこから始めてもよいので、例えば(9 6 5 8)としてもよい。次に、その向かい側の面も、対応する順に並べる。最初の面で(5 8 9 6)とした場合は16 19 20 17となるので、まとめると(5 8 9 6 16 19 20 17)となる。最初の面を(9 6 5 8)とした場合は20 17 16 19となるので、まとめると(9 6 5 8 20 17 16 19)となる。

次の行「(25 27 1)」は、立体の分割数である。細かく分割した方が正確な結果が得られるが、計算に時間がかかる。そのため、流れが複雑なところは細かく、流れが単純なところは粗く分割するのが基本である。ブロックを(a b c d e f g h)で定義し、分割を(j, k, l)で定義した場合、辺a-bと、辺e-fがj分割されることになる。このチュートリアルの場合は、辺5-8と、辺16-19が、(25 27 1)の最初である25分割されることになる。

3行目の「simpleGrading (2.5 1 1)」は、分割のパターンを意味する。「simpleGrading」は「一定の比率で分割をだんだん長くしていく」というものである。辺5-8は、等間隔での分割ではなく、分割区間がだんだんと広くなっていく。辺5-8は、この値が「2.5」と定義されているので、最初(左端)の分割と、最後(右端)の分割の長さの比が1:2.5になっている。この値が「1」の場合は、等間隔で分割される。この値が1よりも小さくなると(例えば0.5)、分割区間がだんだんと狭くなっていく。

なお、隣り合うブロックの分割数と分割ピッチを一致させる必要がある。これは、大変重要なポイントである。

このチュートリアルでは、黄色ブロックの上に桃色ブロックが接しているから、桃色ブロック下辺の分割は、黄色ブロックの分割と一致させる必要がある。黄色ブロックの左に緑ブロックがあるから、黄色ブロックと緑ブロックはY軸方向の分割を一致させる必要がある。

もし一致していないと、blockMeshコマンドを実行した時にエラーとなる。例えば、黄色ブロックの分割数を(24 27 1)に変えてみたら、次のようなエラーが出た。

OpenFOAMのエラーメッセージは、初心者には読みづらいが、上の例では「FOAM FATAL ERROR」の箇所が注目ポイントである。そのすぐ後に「Inconsistent number of face between block pair 3 and 4」とあり、これがエラーの直接原因である。要するに、ブロック3とブロック4の関係に問題あり、ということ。このブロックの番号は、先述したblockMeshDictの「blocks」の節に書かれた0から始まる順番であり、この場合は、ブロック3(黄色)とブロック4(桃色)、つまり「hex (5 8 9 6 16 19 20 17)」と「hex (6 9 10 7 17 20 21 18)」の間に問題があるということである。このエラーが見つかった場合は、例えばこの場合は「blocks」のブロック3とブロック4の定義に矛盾が無いかチェックすること。

次に、境界の定義が必要となる。

境界の名称と種類の定義

このチュートリアルでは、「境界」を5種類に分けている。次の図は、先ほどの立体の壁に、境界の種類別に色を付けて、角度を変えて2つ表示したもの。

図の紫色が「inlet」、緑色が「outlet」、赤色が「upperWall」、水色が「lowerWall」、オレンジ色が「frontAndBack」である。これらの名称は適当に付けられたものであるので、inletを例えばiriguchiなどに変更してもかまわないが、別ファイルでこの名称が何回も使われるので、変更したい場合はそれら全部を変更する必要がある。

このチュートリアルでは「inlet」から水を入れ、「outlet」から水が出る。「upperWall」と「lowerWall」は水を通さない壁、「frontAndBack」は計算しないものとして計算する。まずはblockMeshDictに、これらの名前と境界の種類を定義する。細かい条件は後で別のファイルに記述する。

定義場所は「system/blockMeshDict」の「boundary」の箇所である。

ここで再び点の位置を確認する。

「inlet」は点0, 1, 11, 12で囲まれた四角である。これを立体形状の時計回りに並べる。この例では、例えば(0 1 12 11)である。どこから始めても同じことで、例えば(1 12 11 0)としてもよい。あるいは反時計回りに(0 11 12 1)としてもよい。「inlet」の境界の種類(type)は、液の流入である。境界を液が通過する場合には、「patch」と定義する。つまり、inletは次のように定義される。

inlet
{
    type patch;
    faces
    (
        (0 1 12 11)
    );
}

「outlet」は、点8, 9, 19, 20と、点9, 10, 20, 21で囲まれた四角である。これも4点を時計回り、または反時計回りに並べて面を定義する。outletは、inletとは異なり液が流出する面であるが、境界を液が通過することになるので、ここも種類はpatchとなる。

outlet
{
    type patch;
    faces
    (
        (8 9 20 19)
        (9 10 21 20)
    );
}

「upperWall」は、液が流れないものとして定義する。種類はwallとなる。ここは、先ほどの図の赤い面なので、つまり3面となる。

upperWall
{
    type wall;
    faces
    (
        (1 4 15 12)
        (4 7 18 15)
        (7 10 21 18)
    );
}

「lowerWall」についても「upperWall」と同じような感じで定義する。

2次元解析の場合、「高さ方向」の境界は「empty」として定義する。emptyが定義できるのは、「高さ方向」の厚さが薄く均一な場合に限られる。このチュートリアルは2次元解析であり、先の図ではオレンジ色の面がemptyに当たる。ここを「frontAndBack」として定義する。

frontAndBack
{
    type empty;
    faces
    (
        (0 3 4 1)
        (2 5 6 3)
        (3 6 7 4)
        (5 8 9 6)
        (6 9 10 7)
        (11 14 15 12)
        (13 16 17 14)
        (14 17 18 15)
        (16 19 20 17)
        (17 20 21 18)
    );
}

以上のように、どのブロックとも接しない面は、必ず定義する必要がある。逆に、ブロックとブロックが接する面(つまり流路内部の面)をboundaryで定義すると、エラーになる。

茶色ブロックの追加

前述したように、次のように改造する方針である。

茶色ブロックを作るためには8つの点が必要であるが、茶色ブロックの下面は青色ブロックの上面と共通なので、上面側の4点のみを追加すればよい。追加する4点は、青色ブロック上面の4点から、Y軸方向に移動させた点にすればよい。青ブロックのY軸方向の長さは25.4mmなので、青ブロック上面の4点をY軸方向に25.4ずつ増やせばよい。

青色ブロック上面の点は、上の図から分かるように、点4, 点7, 点15, 点18である。再びblockMeshDictを開いて、verticesの箇所の末尾に追加する。

blockMeshDictの編集
xdg-open system/blockMeshDict

編集後は次の通り。45-48行目が追加部分である。

例えば45行目は、点4、つまり25行目の「(0 25.4 -0.5)」から、yの値を25.4増やしたものである。

ここで一回blockMeshを実行する。エラーが出なければ、paraFoamをblockMeshチェックモードで開く。

blockMeshの実施とblockMeshモードでparaFoam実施
blockMesh
paraFoam -blockmesh

これらを実施して、paraViewが起動してから、Applyした後に適当にマウスで視点を変えると、次の図が現れる。(ただし、見やすくするため、この図は実際よりも厚みを増してある。)

追加した点が認識されていることが分かる。

次に、茶色のブロックを追加する。茶色のブロックは点4, 7, 15, 18, 11, 22, 23, 24, 25の8点からできている。これを並べ替えてブロックを作る。すぐ下の青いブロックが、前述したようにhex (3 6 7 4 14 17 18 15)と定義されているので、これを参考に、同じように8点をつなげればよい。つまり、hex (4 7 23 22 15 18 25 24)となる。辺の分割パターンは、この場合は青ブロックにだけ合わせればよいので、青ブロックの定義をそのまま借用(コピー)する。

上の93-95行目が、追加部分である。

次に、boundaryの定義をする。まず、青ブロックの上面、つまり(4 7 18 15)は、茶色ブロックに挟まれて内部に隠れるため、upperWallから削除する。茶色ブロックの前後の面、つまり(4 7 23 22)と(15 18 25 24)は、frontAndBackに加える。茶色のinlet側の面である(4 15 24 22)、上面である(22 24 25 23)、outlet側の面である(18 25 23 7)は、upperWallとする。結果は次の通り。

上の127行目が消した箇所(青いブロックの上面)、130-132行目が追加した茶色ブロックの上面、162-163行目が茶色ブロックの前面背面である。

修正後の再実施
blockMesh
pisoFoam |grep -E 'Time\s=\s[0-9]*\.[0-9]\s'
paraFoam

結果は次の通り。