OpenFOAMのマルチリージョン（標準ソルバー編 その1 ケースディレクトリ）

# 使用環境
Ubuntu 16.04
OpenFOAM 4.1

# マルチリージョン
OpenFOAMでは固液練成計算などのためにマルチリージョンに対応している。
今回は標準のマルチリージョンソルバーの中身についてまとめてみた。
（一回動かしてみたことのある人用？）

# 標準ソルバー
標準ソルバーとしては以下の二つが入っている。（OF4.1現在）

- chtMultiRegionFoam ([GitHub](https://github.com/OpenFOAM/OpenFOAM-4.x/tree/master/applications/solvers/heatTransfer/chtMultiRegionFoam))
- chtMultiRegionSimpleFoam ([GitHub](https://github.com/OpenFOAM/OpenFOAM-4.x/tree/master/applications/solvers/heatTransfer/chtMultiRegionFoam/chtMultiRegionSimpleFoam))

これらは圧縮性流体/固体の熱（輻射含む）流体を計算するソルバーであり、2者の違いは非定常/定常。
以降はchtMultiRegionFoamを例に説明していく。

## ケースディレクトリ
マルチリージョン化されたケースディレクトリは以下のようになる。
マルチリージョン化はsplitMeshRegionsで行われることを前提とする。

例：tutorials/heatTransfer/MultiRegionFoam/multiRegionHeater ([GitHub](https://github.com/OpenFOAM/OpenFOAM-4.x/tree/master/tutorials/heatTransfer/chtMultiRegionFoam/multiRegionHeater))

> **case**
> ├　**0**
> │　├ cellToRegion
> │　└ **regionA**
> │　　└ cellToRegion
> │　└ **regionB**
> │　　└ cellToRegion
> ├　**constant**
> │　├ regionProperties
> │　├ **polyMesh**
> │　└ **regionA**
> │　　└ **polyMesh**
> │　└ **regionB**
> │　　└ **polyMesh**
> └　**system**
> 　　├ **regionA**
> 　　└ **regionB**

### 0
#### fluid
T　：　温度[K]　他regionとの境界の条件が特殊
U　：　速度[m/s]
p_rgh　：　静圧[Pa]　このソルバーでは位置圧を除いた圧力で計算する
p　：　絶対圧[Pa]　全部calculateでOK
乱流初期条件（k, epsilonなど）
輻射初期条件（Qrなど）

#### solid
T　：　温度[K]　他regionとの境界の条件が特殊
p　：　絶対圧[Pa]　solidThermoを扱う上で必要だが、中身は計算には使われない（と思う）
輻射初期条件（Qrなど）

#### cellToRegion
これは"constant/region/polyMesh/.*Adressing"ファイルと同じく、regionのセルが分割前のメッシュのどれに相当するかを示している。
これを応用すると少し便利だったりするので後日説明するかもしれない。

### constant
#### fluid/g
重力加速度の設定。
#### fluid/radiationProperties
輻射の設定。
#### fluid/thermophysicalProperties
熱力学物性の設定。
#### fluid/turbulenceProperties
乱流の設定。
#### solid/radiationProperties
輻射熱の設定。
#### solid/thermophysicalProperties
熱力学物性の設定。
#### regionProperties
各regionがfluidなのかsolidなのかを保存する。

```c++:case/constant/regionProperties
...
regions (
    fluid      (regionA regionB)
    solid      (regionC regionD)
);
```
ソルバーの中ではこれを

```c++:$FOAM_SOLVERS/heatTransfer/chtMultiRegionFoam/chtMultiRegionFoam.C
57  regionProperties rp(runTime);
```

で読み込み、（このときrpは`HashTable<wordList>`を返す。）

```c++:$FOAM_SOLVERS/heatTransfer/chtMultiRegionFoam/fluid/createFluidMeshes.H
1   const wordList fluidNames(rp["fluid"]);
```

でwordList型のfluidNamesを生成する。
このため、今回のfluidNamesの中身は`2(regionA regionB)`となる。

以降全部のfluidに関して操作する場合は`forAll`を用いて

```c++:
forAll(fluidNames, regionI) {
    const word thisName = fluidNames[regionI]; // 中身はregionAの後regionB
}
```

みたいに使っていく。
#### 任意のregionを追加する場合
例えば2相流の領域を計算するregion"inter"を作りたい場合には

```c++:case/constant/regionProperties
...
regions (
    fluid      (regionA regionB)
    solid      (regionC regionD)
    inter      (regionE)
);
```

```c++:$FOAM_SOLVERS/myFoam/inter/createInterMeshes.H
1   const wordList interNames(rp["inter"]);
```

こんな感じで自由に追加することができる。

### sytem
systemディレクトリ内部もregion毎に設定することになる。
fvScheme, fvSolution, decomposeParDictなどはregion毎に設定し、
controlDictはsystem/のものを使用する。
各regionで対して設定が変わらない場合にはハードリンクなどを使用すると変更の手間が軽減される。

#### fvSolution/frozenFlow
fluidの計算ではfrozenFlowというオプションを設定できる。
場所はここ

```c++:$FOAM_TUTORIALS/heatTransfer/chtMultiRegionFoam/multiRegionHeater/system/bottomWater/fvSolution
PIMPLE
{
    momentumPredictor   on;
    nCorrectors         2;
    nNonOrthogonalCorrectors 0;
    frozenFlow    on;
}
```
これをon/yes/trueにしていると、圧力と速度の計算をスキップして熱の計算のみが行われる。
SIMPLEのほうも同様。
応用方法としては
・計算時間短縮　　：frozenFlow:offで計算し流れを発達させた後にonにする。（温度が圧力・速度に大きく影響しない場合に限る。）
・安定化　　：初めはfrozenFlow:onで温度をある程度安定させてからoffで流体を計算することで、ある程度自然な初期温度条件から流体計算をスタートできる。

※注意：エネルギーで計算するためたまにありえない温度になったりするのでsetFieldsなどを使ってうまいことリセットしたりしましょう。

## ソルバー
マルチリージョンソルバーでは複数のメッシュを読み込み、それぞれについて計算を行う。
### メッシュの読み込み
以下のようにして、複数のfvMeshコンストラクタが生成される。

```c++:$FOAM_SOLVERS/heatTransfer/chtMultiRegionFoam/fluid/createFluidMeshes.H
PtrList<fvMesh> fluidRegions(fluidNames.size());

forAll(fluidNames, i) {
    fluidRegions.set (
        i,
        new fvMesh ( IOobject (fluidNames[i], runTime.timeName(), runTime, IOobject::MUST_READ) )
    );
}
```

#### PtrList
基本的に各領域のメッシュやフィールドなどのオブジェクトはPtrListにまとめられている。
PtrListの仕様は他に譲るとして簡単に使い方を。
例えばotherListというListがあり、それぞれに対してT型のコンストラクタを生成する場合には


```c++:生成
label size = otherList.size();
PtrList<T> myList(size);

forAll(otherList, i) {
    myList.set ( i, new T(引数) );
}
```
ここから値を取り出す場合には

```c++:取り出し
forAll(myList, i) {
    T& a = myList[i];
}
```
### フィールドとモデルの読み込み
これらも同様に各region毎のものをPtrListでまとめられている。

#### fluid
> **thermoFluid**　熱力学モデル　*rhoThermo*
> **rhoFluid**　密度[kg/m3]　*volScalarField*
> **UFluid**　速度[m/s]　*volVectorField*
> **phiFluid**　質量流量[kg/s]　*surfaceScalarField*
> **gFluid**　重力加速度[m/s2]　*uniformDimensionedVectorField*
> **hRefFluid**　基準高さ[m]　*uniformDimensionedScalarField*
> **ghRefFluid**　g×基準高さ[m2/s2]　*dimensionedScalar*
> **ghFluid**　g×volumeの高さ[m2/s2]　*volScalarField*
> **ghfFluid**　g×surfaceの高さ[m2/s2]　*surfaceScalarField*
> **turbulenceFluid**　乱流モデル　*compressible::turbulenceModel*
> **p_rghFluid**　静圧[Pa]　*volScalarField*
> **radiationFluid**　輻射モデル　*radiationradiation::radiationModel*
> **initialMass**　初期総重量[kg]　*scalar*
> **KFluid**　運動エネルギー[J/m3]　*volScalarField*
> **dpdtFluid**　圧力変化[Pa/s]　*volScalarField*
> **frozenFlowFluid**　圧力速度計算をスキップするかどうか　*bool* 
> **MRFFluid**　メッシュが動く場合？（使ったことないです）　*IOMRFZoneList*
> **fvOptionFluid** fvOptionの読み込み　*fv::IOoptionList*

#### solid
> **thermos** 固体の熱力学モデル *solidThermo*
> **radiations** 輻射モデル *radiation::radiationModel*
> **solidHeatSources** fvOptionの読み込み *fv::IOoptionList*
> isotropic 熱伝導率が一定でない場合にはこれで色々やる



続きはまた後日

間違ってる部分があれば教えてください。