OpenFOAM: patchを分割する

# メッシュのpatchを後から分割したい
OpenFOAMでメッシュを作成した後に境界面（patch)を分割して、新しいpatchを作成する手順です。

具体例が下図です。wallという名前のpatchを２分割して、wallとwall1というpatchをもつメッシュにします。

元のメッシュ
![mono.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43609/83e7e460-5f0b-62e4-5198-9d66989f43b6.png)

分割後のメッシュ
![divided.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43609/ed08dcb2-83d9-12b4-fe7a-2324b1a73633.png)

# 具体的な手順
1. setSetで新しいpatchになるfaceSetを作る。
2. 上でつくったfaceSetをもとにして、createPatchを実行して、patchを作成する。

createPatchがpatchを作るコマンドです。このコマンドで、setからpatchを作成できます。

詳細です。
## blockMeshでメッシュ作成
メッシュ自体はblockMeshでもなんでもいいので作成します。今回はサイズ1x1x10の直方体を例として作成します。patchはすべてwallとします。

```c++:blockMeshDict
/*--------------------------------*- C++ -*----------------------------------*\
| =========                 |                                                 |
| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|  \\    /   O peration     | Version:  2.3.0                                 |
|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
|    \\/     M anipulation  |                                                 |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      blockMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

convertToMeters 1;

vertices
(
    (0 0 0)
    (1 0 0)
    (1 1 0)
    (0 1 0)
    (0 0 10)
    (1 0 10)
    (1 1 10)
    (0 1 10)
);

blocks
(
    hex (0 1 2 3 4 5 6 7) (5 5 20) simpleGrading (1 1 1)
);

edges
(
);

boundary
(
    wall
    {
        type wall;
        faces
        (
            (3 7 6 2)
            (0 4 7 3)
            (2 6 5 1)
            (1 5 4 0)
            (0 3 2 1)
            (4 5 6 7) 
        );
    }
);

mergePatchPairs
(
);

// ************************************************************************* //
```

## setSetでfaceSetの作成
setSetはsetを作るコマンドです。setは具体的にはcellSetやfaceSetなど、各要素の集合体みたいなものです。（setとzoneの違いがいまいちわからないので、ご存知だったら教えて下さい。）新しいpatchになる部分を表すfaceSetを作成します。

やり方としては
1. 既存のpatch（ここではwall）に対応するfaceSetのf0を作成。
2. 新しいpatchになる領域を含んだcellSet（セルの集合体）c0を作成。
3. セルセットc0からfaceSet f1を作成。
4. 最初に作ったfaceSet f0からfaceSet f1を削除して、新しいpatchになるfaceSetを作成。

setSetだと対話的に処理が行われます。以上の処理をコマンドで入力すると以下。

```bash
readline>faceSet f0 new patchToFace wall
readline>cellSet c0 new boxToCell (0 0 0) (1 1 5)
readline>faceSet f1 new cellToFace c0 all
readline>faceSet f0 delete faceToFace f1
```

１行目でwallというpatchからfaceSetを作成。
２行目で下半分の領域（（0 0 0)と(1 1 5)を対角線に配置した直方体の領域）を含むcellSetを作成。
3行目でcellSet c0からfaceSet f1を作成。最後のオプションをallにして、セルセット内の全faceを含むfaceSetを作成。オプションでbothを選択できますが、そうすると、境界上のfaceが選択されません。
４行目でfaceSetの差分を取ってます。

topoSetDictを作成すると、上記の処理をtopoSetコマンド一発でできます。

```c++:system/topoSetDict
/*--------------------------------*- C++ -*----------------------------------*\
| =========                 |                                                 |
| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|  \\    /   O peration     | Version:  2.2.2                                 |
|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
|    \\/     M anipulation  |                                                 |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      topoSetDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

actions
(
 {
     name    f0;
     type    faceSet;
     action  new;
     source  patchToFace;
        sourceInfo
            {
                name    "wall";
            }
 }
 {
     name    c0;
     type    cellSet;
     action  new;
     source  boxToCell;
     sourceInfo
            {
                box (0 0 0) (1 1 5);
            }
 }
 {
     name    f1;
     type    faceSet;
     action  new;
     source  cellToFace;
     sourceInfo
            {
                set c0;
                option all;
            }
 }
 {
     name    f0;
     type    faceSet;
     action  delete;
     source  faceToFace;
     sourceInfo
            {
                set f1;
            }
 }
);
```

## createPatchコマンドでpatchを作成
faceSet f0は直方体の上半分の境界のfaceを取り出した状態になっています。このfaceSetを使って、patchを作成します。新しいpatchの名前はwall1にします。

system内にcreatePatchDictを作成します。

```c++:system/createPatchDict
FoamFile
{
    version    2.0;
    format     ascii;
    class      dictionary;
    location   "system";
    object     createPatchDict;
}

pointSync false;

patches
(
    {
        name    "wall1";
        patchInfo
        {
            type    wall;
        }
        constructFrom set;
        set     f0;
    }
);
```

既存のメッシュ情報に上書きするために-overwriteオプションつけて、createPatchを実行

```bash
createPatch -overwrite
```

これでpatchが分割できました。

blockMeshDictを修正してpatchを増やそうとすると、点を追加して、境界面の設定を追加してと、かなり大変です。blockMeshDictの修正なしで、境界面を修正できるので、手間が省けるかと思います。