Docker-ComposeでOpenFOAMの開発環境を構築

#はじめに
DockerでOpenFOAMの開発および計算環境を構築する方法をメモしておく．
OpenFOAMはfundation版を想定しています．

これらの内容はgithub上で公開しているので，参考にしてもらいたい．
https://github.com/matsubaraDaisuke/openfoam-docker-start

# 環境
dockerとdocker-composeはインストール済みとする．

docker version  19.03.4
docker-compose version 1.24.1

# 構成
ディレクトリ構成は以下のものとします．

``` 
project
├ docker-compose.yml
├ docker
|　 └ openfoam
| 　　　└ Dockerfile
└ of-develop(このディレクトリ内で開発する)
```

# 環境構築

## 1.ディレクトリ作成
上の構成を参考にディレクトリとファイルを作成するか，githubからcloneしてください．

``` terminal
git clone https://github.com/matsubaraDaisuke/openfoam-docker-start.git
cd openfoam-docker-start
```
## 2.docker-compose.yml
今回利用するコンテナはopenfoamのみなので，以下のように書きます．pythonのライブラリなどを組み合わせたい場合は、必要に応じて増やしていきます

`volumes:`のところでopenfoamの`$WM_PROJECT_USER_DIR`にマウントしていることがわかります．


``` docker-compose.yml
version: '3'

services:
    openfoam:
      container_name: openfoam
      build: ./docker/openfoam
      volumes:
      - ./of-develop:/home/openfoam
```
## 3.Dockerfile作成
OpenFOAM用のDockerfileを作成します．
今回はversion7を利用します．
https://hub.docker.com/r/openfoam/openfoam7-paraview56

別のバージョンを使いたい場合は，以下のリンクから別のコンテナを探してください．
https://hub.docker.com/r/openfoam/

```dockerfile:./openfoam/Dockerfile
FROM openfoam/openfoam7-paraview56

WORKDIR /home/openfoam
```

## 4.動作確認

`docker-compose.yml`のあるディレクトリで以下のコマンドをうつと，ビルドが始まります．

``` terminal:host
$ docker-compose up --build
```
問題なく終了したら，以下のコマンドでopenfoamのコンテナ内に入ることができます．

``` terminal:host
$ docker-compose run openfoam /bin/sh
```

コンテナ内で`pwd`すると`/home/openfoam`にいることがわかります．
また，適当にファイルを作成`touch a.foam`すると，ホスト側の`of-develop`内に`a.foam`が出力されることが確認できます．

<img width="882" alt="スクリーンショット 2020-01-11 20.04.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/0e4844e5-0930-ff4b-ab6c-1ff5c96b38f3.png">

OpenFOAMもそのまま利用できる状態になっていることが確認できます．

``` terminal:container
$ simpleFoam -help

Usage: simpleFoam [OPTIONS]
options:
  -case <dir>       specify alternate case directory, default is the cwd
  -fileHandler <handler>
                    override the fileHandler
  -hostRoots <(((host1 dir1) .. (hostN dirN))>
                    slave root directories (per host) for distributed running
  -libs <(lib1 .. libN)>
                    pre-load libraries
  -listFunctionObjects
                    List functionObjects
  -listFvOptions    List fvOptions
  -listRegisteredSwitches
                    List switches registered for run-time modification
  -listScalarBCs    List scalar field boundary conditions (fvPatchField<scalar>)
  -listSwitches     List switches declared in libraries but not set in
                    etc/controlDict
  -listTurbulenceModels
                    List turbulenceModels
  -listUnsetSwitches
                    List switches declared in libraries but not set in
                    etc/controlDict
  -listVectorBCs    List vector field boundary conditions (fvPatchField<vector>)
  -noFunctionObjects
                    do not execute functionObjects
  -parallel         run in parallel
  -postProcess      Execute functionObjects only
  -roots <(dir1 .. dirN)>
                    slave root directories for distributed running
  -srcDoc           display source code in browser
  -doc              display application documentation in browser
  -help             print the usage

Using: OpenFOAM-7 (see https://openfoam.org)
Build: *******
```


# 計算のインプットファイルと環境を共有したい場合
（計算自体も相手に押し付けたい人向け）

まず，計算結果を共有する例を作成してみます．
コンテナ内で，チュートリアルのpitzDailyをコピーしてきます．

``` terminal:container
$ cp -r $WM_PROJECT_DIR/tutorials/incompressible/simpleFoam/pitzDaily .
```

<img width="1063" alt="スクリーンショット 2020-01-11 20.14.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/ca5ffa10-582a-c6d5-da88-95ec053638d3.png">

of-developディレクトリ 下にケースファイルが置かれています．
この様な状態で，docker-compose.ymlなどとセットで送ると良いでしょう．
データ容量も303KBと軽量です．

データを受け取った側は，上の動作確認の項目と同じ操作をしたのち，ケースファイルの中で計算を実行すると良いでしょう．

``` terminal:container
$ cd pitzDaily
$ blockMesh
$ simpleFoam
```
計算結果が，`of-develo/pitzDaily`ディレクトリに出力されます．

ケースファイルを送る側の人は，実行に必要なコマンドを`Makefile`などに記述してあげると，より親切だと思われます．

このように、計算とインプットファイルと計算環境の情報をセットにしてgitなどで管理することで、技術的負債となることを避けることができます．





# ソルバーの開発をしたい場合

適当なソルバーをコピーしてきます．

``` terminal:container
cp -r $WM_PROJECT_DIR/applications/solvers/basic/laplacianFoam/ .
```

ためしに`laplacianFoam2`というソルバーを作成してみましょう．

ファイル名を変更

``` terminal:container
mv laplacianFoam.C  laplacianFoam2.C
```

`laplacianFoam/Make/files`を以下のように修正

```txt:laplacianFoam/Make/files
laplacianFoam2.C

EXE = $(FOAM_USER_APPBIN)/laplacianFoam2
```

<img width="1120" alt="スクリーンショット 2020-01-11 20.32.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/924dc810-6412-c012-1163-ca9d75c920c4.png">


最後にコンパイルします．

``` terminal:container(laplacianFoam直下で)
$ wmake
```

成功すると，以下のように実行できると思います．

``` terminal:container
$ laplacianFoam2 -help

Usage: laplacianFoam2 [OPTIONS]
options:
  -case <dir>       specify alternate case directory, default is the cwd
  -fileHandler <handler>
                    override the fileHandler
  -hostRoots <(((host1 dir1) .. (hostN dirN))>
                    slave root directories (per host) for distributed running
  -libs <(lib1 .. libN)>
                    pre-load libraries
  -listFunctionObjects
                    List functionObjects
  -listFvOptions    List fvOptions
  -listRegisteredSwitches
                    List switches registered for run-time modification
  -listScalarBCs    List scalar field boundary conditions (fvPatchField<scalar>)
  -listSwitches     List switches declared in libraries but not set in
                    etc/controlDict
  -listUnsetSwitches
                    List switches declared in libraries but not set in
                    etc/controlDict
  -listVectorBCs    List vector field boundary conditions (fvPatchField<vector>)
  -noFunctionObjects
                    do not execute functionObjects
  -parallel         run in parallel
  -roots <(dir1 .. dirN)>
                    slave root directories for distributed running
  -srcDoc           display source code in browser
  -doc              display application documentation in browser
  -help             print the usage

Using: OpenFOAM-7 (see https://openfoam.org)
Build: ******
```

以上の方法で，改造するソルバーの部分のみが，ホスト側から見える状況で開発を進めることができます．バージョンの違いによる結果の比較等も楽に行うことができるでしょう．
今回は無理にcomposeにする必要はないと思いますがが、開発途中で様々なイメージを組み合わせたくなった場合を想定してこのようにしています．