数値流体ソルバーOpenFOAMで桃をどんぶらこする

## はじめに
OpenFOAMの重合格子、二相流計算の練習として、適当な浮体の動揺計算を行ってみる。

## 参考にしたチュートリアル
overInterDyMFoamのfloatingBodyでは、角柱形状の浮体の動揺を再現している。
これを改良して、指定の形状データを取り扱えるようにする。
https://www.openfoam.com/documentation/guides/latest/doc/guide-overset.html

チュートリアルフォルダの中には、```background```と、```floatingBody```の2つのフォルダが存在する。```background```は重合計算のバックグラウンド領域、```floatingBody```は重合計算のオーバーセット領域である。
オーバーセット領域はオブジェクトの運動に合わせて動き、外周部のセルでバックグラウンドとの流場情報のやり取りを行う。
![スクリーンショット 2020-08-23 2.09.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578196/9d4edade-71fb-fdd4-2efd-ad003946ef05.png)

以下、要点のみ。

## 3Dデータの用意
Fusion360という定番のソフトで3次元形状を作成する。
![スクリーンショット 2020-08-13 17.46.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578196/c99ecc90-19aa-d47c-c931-613d4912b771.png)
桃の中心が座標原点。

## 計算格子の用意
snappyHexMeshで計算格子を作成する。motorBikeのチュートリアルから引っ張ってきた。

```terminal:/floatingObject/system/snappyHexMeshDict
/*--------------------------------*- C++ -*----------------------------------*\
| =========                 |                                                 |
| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|  \\    /   O peration     | Version:  v1912                                 |
|   \\  /    A nd           | Website:  www.openfoam.com                      |
|    \\/     M anipulation  |                                                 |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      snappyHexMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

castellatedMesh true;
snap            true;
addLayers       true;

geometry
{
    object.stl
    {
        type triSurfaceMesh;
        name floatingObject;
    }
}

// Settings for the castellatedMesh generation.
castellatedMeshControls
{
    maxLocalCells 100000;
    maxGlobalCells 2000000;
    minRefinementCells 10;
    maxLoadUnbalance 0.10;
    nCellsBetweenLevels 3;

    features
    (
        {
            file "object.eMesh";
            level 3;
        }
    );

    refinementSurfaces
    {
        floatingObject
        {
            level (2 3);
            patchInfo
            {
                type wall;
                inGroups (floatingObject);
            }
        }
    }

    resolveFeatureAngle 30;

    refinementRegions
    {
    }

    locationInMesh (0.4999 0.4999 0.4999);
}

// Settings for the snapping.
snapControls
{
    nSmoothPatch 3;
    tolerance 2.0;
    nSolveIter 30;
    nRelaxIter 5;
    nFeatureSnapIter 10;
    implicitFeatureSnap false;
    explicitFeatureSnap true;
    multiRegionFeatureSnap false;
}

// Settings for the layer addition.
addLayersControls
{
    relativeSizes true;

    layers
    {
        floatingObject
        {
            nSurfaceLayers 5;
        }
    }

    expansionRatio 1.0;
    finalLayerThickness 0.3;
    minThickness 0.1;
    nGrow 0;
    featureAngle 60;
    slipFeatureAngle 30;
    nRelaxIter 3;
    nSmoothSurfaceNormals 1;
    nSmoothNormals 3;
    nSmoothThickness 10;
    maxFaceThicknessRatio 0.5;
    maxThicknessToMedialRatio 0.3;
    minMedialAxisAngle 90;
    nBufferCellsNoExtrude 0;
    nLayerIter 50;
}
// ************************************************************************* //

```

![peachmesh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578196/09529413-8982-c30a-df32-0db3e929d150.png)

格子が若干粗く、桃の割れ目や葉との接合部が崩れている。
が、とりあえずこのまま行ってみる。

## 領域の設定
topoSetで領域分けを行う。
```insidePoints ((1.9999 1.9999 1.9999))```を持つ格子（バックグラウンド領域）をc0と定義し、そのinvert（オーバーセット領域）をc1と定義する。

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

actions
(
    {
        name    c0;
        type    cellSet;
        action  new;
        source  regionToCell;
        insidePoints ((1.9999 1.9999 1.9999));
    }
    {
        name    c1;
        type    cellSet;
        action  new;
        source  cellToCell;
        set     c0;
    }
    {
        name    c1;
        type    cellSet;
        action  invert;
    }
);

// ************************************************************************* //
```
先程領域を定義したc0に```zoneID=0```、c1に```zoneID=1```というスカラー値を与える。

ついでに```defaultFieldValues(volScalarFieldValue alpha.water 0);```で一旦計算領域全体を```alpha.water=0```(気相)にし、boxToCellで指定した領域を```alpha.water=1```(液相)に変更しておく。
ここでは、1回目のboxToCellで水面（z=0）以下を液相にし、その後x>1、y>1、z<0.5の領域に水柱を立てている。


```terminal:/background/system/setFieldDict
/*--------------------------------*- C++ -*----------------------------------*\
| =========                 |                                                 |
| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|  \\    /   O peration     | Version:  v1912                                 |
|   \\  /    A nd           | Website:  www.openfoam.com                      |
|    \\/     M anipulation  |                                                 |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      setFieldsDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

defaultFieldValues
(
    volScalarFieldValue alpha.water 0
    volScalarFieldValue zoneID 123
);

regions
(
    cellToCell
    {
        set c0;
        fieldValues
        (
            volScalarFieldValue zoneID 0
        );
    }
    cellToCell
    {
        set c1;
        fieldValues
        (
            volScalarFieldValue zoneID 1
        );
    }

    boxToCell
    {
        box ( -100 -100 -100 ) ( 100 100 0.0 );
        fieldValues ( volScalarFieldValue alpha.water 1 );
    }
    boxToCell
    {
        box ( 1.0 1.0 -100 ) ( 100 100 0.5 );
        fieldValues ( volScalarFieldValue alpha.water 1 );
    }
);
// ************************************************************************* //
```

他の設定は省略。基本的にチュートリアルそのままで、名前や領域の大きさのみ変更する。

## 計算結果
無事にどんぶらこできた。
（動画の埋め込み表示がうまくいかない...）

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">計算してみた。<a href="https://t.co/SPvdbvZbuL">https://t.co/SPvdbvZbuL</a></p>&mdash; クエン酸 (@momomo15875) <a href="https://twitter.com/momomo15875/status/1297416249006202880?ref_src=twsrc%5Etfw">August 23, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>