Google compute engine で OpenFOAM を動かしてみた

この記事は、[Google Cloud Platform](https://cloud.google.com/) の Google compute engine を使ってクラウド上でフリーの計算流体力学 (CFD) ソフトウェア OpenFOAM を動かしてみたメモです。

OpenFOAM で 3 次元の部屋をイメージした重たい問題を解きたいと思い、家のノートパソコンよりも強い環境がないかと考えた結果、クラウドコンピューティングを試してみるに至りました。（Google Cloud Platform はしばらく無料で使えます。）
ここでは、簡単のためまずはチュートリアルの簡単な例を使ってサーバー上での計算と可視化を行い、それから並列計算を試してみます。

# 環境

- サーバー側（Google compute engine）
    - Ubuntu 18.04
    - OpenFOAM 6 with Paraview 5.6.0
- クライアント側（家のノートパソコン）
    - Windows 10
    - putty
    - Paraview 5.6.0

Google compute engine でサーバーを用意する部分についてはここでは省略します。
また、putty については Google compute engine の[このドキュメント](https://cloud.google.com/compute/docs/instances/connecting-advanced#thirdpartytools)に設定の仕方が書いてあり、これに従って ssh 接続の公開鍵を Google 側に登録しておきます。
Windows 上の Paraview については[ホームページ](https://www.paraview.org/)からインストールしておきます。

サーバー上の OpenFOAM については OpenFOAM の[このドキュメント](https://openfoam.org/download/6-ubuntu/)にあるように

~~~~{.sh}
sudo sh -c "wget -O - http://dl.openfoam.org/gpg.key | apt-key add -"
sudo add-apt-repository http://dl.openfoam.org/ubuntu
sudo apt-get update
sudo apt-get -y install openfoam6
~~~~

を順番に実行した後、~/.bashrcに

~~~~{.sh}
source /opt/openfoam6/etc/bashrc
~~~~

を追加しておけば bash の初期化時に設定がされるようになります。
最後に、OpenFOAM では `FOAM_RUN` 環境変数のパスの位置で作業をすることが推奨されているため、`mkdir -p $FOAM_RUN` でそのフォルダを用意しておきます。

# OpenFOAM による計算

ここでは、インストール時についてくるチュートリアルのケースで説明をします。

サーバー側で適当なフォルダに移動し、

~~~~{.sh}
cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity ./
~~~~

でチュートリアルのケースを1つコピーしてきます。
そして cavity フォルダの中に移動し、

~~~~{.sh}
blockMesh
icoFoam >& log
~~~~

と実行すれば一通り計算が終わります。（うまくいったかどうかは log ファイルの中を確認してみてください。）
このあとの処理のため、

~~~~{.sh}
touch result.foam
~~~~

で空のファイルを作っておきましょう。（拡張子が .foam であれば何でもいいです。）

# ssh 経由の Paraview による可視化

遠隔のサーバーにあるデータ上のデータを可視化するため、ここでは putty についてくる plink と pvserver を使います。

まず、Windows 側のコマンドプロンプトで

~~~~{.sh}
plink -ssh -L 11111:localhost:11111 <user-name>@<server-IP> -i <private-key>
~~~~

の形式でコマンドを実行します。`<user-name>` はサーバー上でのユーザー名（シェル上で表示されているもの）、`<server-IP>` はサーバーの外部 IP アドレス（Google compute engine のコンソール上に表示されるもの）で、`<private-key>` は ssh 接続の秘密鍵のファイルへのパスです。
うまくつながった場合、「Access granted. Press Return to begin session.」と出ますので、Enter を押して続行しておきます。
これでサーバーとの間に ssh のリンクができました。これを利用して Paraview を動かすため、サーバー側で

~~~~{.sh}
pvserver &
~~~~

を実行します。そして、Windows 側で Paraview を起動します。メニューの File -> Connect... コマンドをクリックし、出てくるウィンドウで Add Server ボタンを押します。そして、出てくる画面で

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229492/88b2da31-c20e-85da-37f9-a1dbe17833ab.png)

のように設定をし、Configure をクリックします。あとは、追加された localhost tunnel をダブルクリックすれば接続を開始します。
接続ができると、下の図のように Pipeline Browser の欄の最初が localhost tunnel になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229492/5b1162af-eca5-778d-38aa-7d39bd8a0ae1.png)

これで接続ができましたので、あとは普通にファイルを開くときのようにツールバーの Open ボタンやメニューの File -> Open をクリックします。すると、サーバーのカレントディレクトリの位置でダイアログボックスが開きますので、先ほど作った result.foam ファイルを開きます。
あとは、Apply ボタンを押すとデータが読み込まれ、結果が表示されます。

# 並列計算

次は、並列計算をしてみます。
今は試すだけのためメッシュサイズはそのままにしておき、cavity フォルダの中の system フォルダ内に次のような内容の decomposeParDict ファイルを作ります。

~~~~{decomposeParDict}
/*--------------------------------*- C++ -*----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Version:  6
     \\/     M anipulation  |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    location    "system";
    object      decomposeParDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

numberOfSubdomains 3;

method          scotch;

// ************************************************************************* //
~~~~

ここで、numberOfSubdomains の欄は並列計算のプロセス数になるため、適宜変えてください。その数に領域を分割してくれます。
なお、分割の結果が見たい場合は system/controlDict の最後に

~~~~
libs
(
    "libfieldFunctionObjects.so"
);
functions
{
    func
    {
        type processorField;
        outputControl   outputTime;
        outputInterval  1;
    }
}
~~~~

を足しておくと、あとで Paraview 上で processorID というフィールドを表示することにより分割の結果を見ることができます。
設定を足したら

~~~~{.sh}
decomposePar
mpirun -np 3 icoFoam -parallel >& log
reconstructPar
~~~~

を順に実行するとそれぞれ領域の分割、並列計算、分割された結果の統合ができます。
（メッシュが小さすぎるため、並列化をしたことによりかえって遅くなるかもしれません。）
先ほどと同様に Paraview で結果を確認しましょう。

（追記）この記事を一旦書いた後に調べてみたところ、1 つのコアあたり 50,000 セル程度になるよう調節すると速くなるという意見がネットのフォーラムの[ここ](https://www.cfd-online.com/Forums/openfoam-solving/196250-openfoam-parallel-calculation-performance-study-half-performance-mpirun.html)や[ここ](https://www.cfd-online.com/Forums/openfoam-solving/58408-mpirun-how-many-processors.html)にありました。また、実験をしている[この記事](https://pdfs.semanticscholar.org/0e16/d479b2888874843694256d337483cf857e19.pdf)でも、コアあたりのセル数が同様の規模のときに最も良いパフォーマンスが得られたとありました。この数字は当然環境依存ですが、目安としてこのくらいのオーダーだということをここに追記しておきます。

# あとがき

今回は、Google のクラウドコンピューティングを利用して OpenFOAM により並列計算を行うテストをしました。これを利用して実際にメッシュの点数が非常に多い問題を解いて遊んでいきたいと思います。