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

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

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

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

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

```linux:チュートリアル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（再生）ボタンを押すと、結果がアニメーション表示される。
<img width="438" alt="無題15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/1bb6f733-d947-16c2-6a0b-b5ad0fa3ba82.png">
左上から流入し、右側から流出する。その際、左下に角があるため、この個所に吹き溜まり生じ、途中に渦ができる様子がシミュレーションされる。

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

#流路形状の構造の説明
##流路はブロックからできている
blockMeshを使う場合、全ての領域は、点8個から成る四角いブロックから構成されている。このチュートリアルの流路は、5つのブロックからできている。
<img width="270" alt="無題16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/9ecd213e-c4fd-df59-2ce6-c4f53d7aa0d3.png">
上の図を見て分かるように、ブロック同士は面全体で結合している。なお、この図は、見やすくするため、オリジナルよりも厚さを増やしている。

オリジナルのブロック構成は次のようになっている。
<img width="388" alt="無題17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/1317dced-760f-b21e-0572-f161dfc921dc.png">
オリジナルの青ブロックの上に、もう一つブロックを乗せたいとする。この場合、次の図のようにブロックを足すことはできない、
<img width="388" alt="無題17a.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/0ec9337c-2fce-d3a0-ce61-2517ced5e411.png">
追加した茶色いブロックと、元からある青いブロックが、全面では接触していない（青いブロックの右半分のみと接触している）ためである。この形で解析をしたい場合には、元からあるブロックも分割して、例えば、次の図のようにする必要がある。
<img width="388" alt="無題17c.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/cc0f186d-d461-c4e0-08f6-47dc30684634.png">
この修正には時間がかかるので、今回は簡単に、次の図のように改造することにする。
<img width="388" alt="無題17b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/8f4f618a-18fb-131a-4239-95ae61aaa7c0.png">
以下でこの改造方法を理解すれば、もう一つ上の分割も、手間はかかるが、同様に実行することができるようになる。

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

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

```linux:blockMeshDictの編集
xdg-open system/blockMeshDict
```

すると、次のようなファイルが開く。（ただし行末で「// 0」のように書かれている箇所は、私が書き足した注釈です。）
<img width="438" alt="無題20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/fd6d8923-ed3a-2827-bb03-ec4ba946b9a7.png">
19行目の「vertices」で定義されているのが、頂点である。行の上の方から点0、点1...となっており、最後が点21である。以下、この点の番号で、図形を定義することになる。点の番号は、（1ではなく）0から始まることに注意。番号は自動で付与されるので、以下で立体形状を定義した後に、気が変わってverticesの途中の行を削除すると、立体形状の定義を全部書き換える必要がある。

##立体と分割の定義
立体の定義では、まずはブロックを定義する。このチュートリアルの黄色（右下）のブロックは、次のように構成されている。
<img width="254" alt="無題21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/08886aba-09aa-aa7f-dff0-cf8c7b6fd2f5.png">
つまり、点5, 6, 8, 9, 16, 17, 19, 20の8点で構成されている。このブロックの定義は、先ほどのblockMeshDictファイルの「blocks」の箇所に書かれている。
<img width="439" alt="無題22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/0819eaef-163b-5bc1-5dae-34b376526360.png">
ブロックの順番に縛りは無いが、このブロックにも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）を反時計回りに並べる。例えば次の図の緑の矢印の順につなげる。
<img width="255" alt="無題21b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/8b24b564-3afb-c26f-2a6b-3038428bdc47.png">
上の図の例では、(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分割されることになる。
<img width="381" alt="無題21d.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/2a206c53-79d3-f131-c689-b371cbd7f669.png">
3行目の「simpleGrading (2.5 1 1)」は、分割のパターンを意味する。「simpleGrading」は「一定の比率で分割をだんだん長くしていく」というものである。辺5-8は、等間隔での分割ではなく、分割区間がだんだんと広くなっていく。辺5-8は、この値が「2.5」と定義されているので、最初（左端）の分割と、最後（右端）の分割の長さの比が1:2.5になっている。この値が「1」の場合は、等間隔で分割される。この値が1よりも小さくなると（例えば0.5）、分割区間がだんだんと狭くなっていく。

なお、隣り合うブロックの分割数と分割ピッチを一致させる必要がある。これは、大変重要なポイントである。
<img width="340" alt="無題23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/aa0de1eb-a2b3-4f28-f3c0-22d24aff4993.png">
このチュートリアルでは、黄色ブロックの上に桃色ブロックが接しているから、桃色ブロック下辺の分割は、黄色ブロックの分割と一致させる必要がある。黄色ブロックの左に緑ブロックがあるから、黄色ブロックと緑ブロックはY軸方向の分割を一致させる必要がある。

もし一致していないと、blockMeshコマンドを実行した時にエラーとなる。例えば、黄色ブロックの分割数を(24 27 1)に変えてみたら、次のようなエラーが出た。
<img width="419" alt="無題24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/13467658-571a-9230-c1b1-3023ef47d38a.png">
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つ表示したもの。
<img width="410" alt="無題25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/eb885cba-6512-ccab-ded2-44190efa7b51.png">
図の紫色が「inlet」、緑色が「outlet」、赤色が「upperWall」、水色が「lowerWall」、オレンジ色が「frontAndBack」である。これらの名称は適当に付けられたものであるので、inletを例えばiriguchiなどに変更してもかまわないが、別ファイルでこの名称が何回も使われるので、変更したい場合はそれら全部を変更する必要がある。

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

定義場所は「system/blockMeshDict」の「boundary」の箇所である。
<img width="441" alt="無題26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/7301f4ff-ad9b-dc26-33af-ea889b60b800.png">
ここで再び点の位置を確認する。
<img width="270" alt="無題16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/ca005b7b-2d1e-63c1-b2f7-69b30e22d864.png">
「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で定義すると、エラーになる。

#茶色ブロックの追加
前述したように、次のように改造する方針である。
<img width="388" alt="無題17b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/8f4f618a-18fb-131a-4239-95ae61aaa7c0.png">
茶色ブロックを作るためには8つの点が必要であるが、茶色ブロックの下面は青色ブロックの上面と共通なので、上面側の4点のみを追加すればよい。追加する4点は、青色ブロック上面の4点から、Y軸方向に移動させた点にすればよい。青ブロックのY軸方向の長さは25.4mmなので、青ブロック上面の4点をY軸方向に25.4ずつ増やせばよい。
<img width="270" alt="無題16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/ca005b7b-2d1e-63c1-b2f7-69b30e22d864.png">
青色ブロック上面の点は、上の図から分かるように、点4, 点7, 点15, 点18である。再びblockMeshDictを開いて、verticesの箇所の末尾に追加する。 

```linux:blockMeshDictの編集
xdg-open system/blockMeshDict
```

編集後は次の通り。45-48行目が追加部分である。
<img width="409" alt="無題28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/d44810c8-0da5-1a4f-ce47-143716c9f7f2.png">
例えば45行目は、点4、つまり25行目の「(0 25.4 -0.5)」から、yの値を25.4増やしたものである。

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

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

これらを実施して、paraViewが起動してから、Applyした後に適当にマウスで視点を変えると、次の図が現れる。（ただし、見やすくするため、この図は実際よりも厚みを増してある。）
<img width="280" alt="無題27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/2d56fcfd-28e5-ec55-a960-7ce8b2d2e8d3.png">
追加した点が認識されていることが分かる。

次に、茶色のブロックを追加する。茶色のブロックは点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)となる。辺の分割パターンは、この場合は青ブロックにだけ合わせればよいので、青ブロックの定義をそのまま借用（コピー）する。
<img width="439" alt="無題29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/3994b3f7-7e4b-c59b-1e11-09d8fef73462.png">
上の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とする。結果は次の通り。
<img width="442" alt="無題31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/4bb8170a-396c-ee65-ba62-521e6f649610.png">
上の127行目が消した箇所（青いブロックの上面）、130-132行目が追加した茶色ブロックの上面、162-163行目が茶色ブロックの前面背面である。

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

結果は次の通り。
<img width="348" alt="無題30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672686/e9891c08-d785-0ca9-f5c6-4d96b3b4fe1d.png">