OpenFOAMにolaFlowをインストールして、造波させる

# olaFlowとは？
造波吸収機能を持つOpenFOAMのライブラリ・ソルバです。
これを用いることで実際の海の様子や実験水路で発生する波を再現できると思います。

詳しくは[こちら](https://olaflow.github.io/)から。
# 環境
- M2 Mac
- OpenFOAM v2012
- ParaView -5.10.1 

# 対象とする人
- OpenFOAMのインストール方法が気になる方
- olaFlowのインストール方法が気になる方
- 海岸・海洋の分野に関心があり、とにかく数値計算ができる環境を整えたい方

# OpenFOAM v2012をインストールする
以前の記事でもOpenFOAMのインストールを行いましたが、
今回はOpenFOAMをインストール方法が若干異なる（謎の工夫をした）ので説明を加えます。

以前の記事↓
https://qiita.com/kairi_sekiya/items/d946d75352106ab944dd

まずは、ローカル環境に作業用ディレクトリとDockerfileを作成します。
~~~
$ cd $HOME
$ mkdir OpenFOAM
$ cd OpenFOAM
$ touch Dockerfile
~~~

Dockerfileの中身はこんな感じにする。
シェルスクリプト(copy_openfoam_tutorials.sh)は後ほど作成します。

~~~md:Dockerfile
FROM opencfd/openfoam-default:2012
RUN apt update && \
  apt install  -y tree nano
COPY copy_openfoam_tutorials.sh /usr/local/bin/
# スクリプトに実行権限を付与
RUN chmod +x /usr/local/bin/copy_openfoam_tutorials.sh
~~~

次にバインドマウントの設定を行います。

コンテナを削除するとコンテナ内のデータも消えてしまいます。
それはイヤなので、バインドマウントという機能を用いてデータを永続化します。
これにより、コンテナ内とローカルのファイルが同期できます。

そこで、今回は「Docker Compose」というソフトウェアを使用します。とはいっても、別途インストールする必要はないです。
```
# 作業用ディレクトリに移動
$ cd $HOME/OpenFOAM

# compose.ymlファイルを作成する
$ touch compose.yml
```
compose.ymlの中身はこのようにしました。
なお、バインドマウント関連以外も多々工夫をしました。
~~~md:compose.yaml
# servicesにコンテナの定義を書く
services:
  # コンテナ名を指定
  myopenfoam:
    container_name: container_openfoam
    # バインドマウント
    volumes:
      - /Users/<user_name>/OpenFOAM/run/:/root/OpenFOAM/-v2012/run/
    # イメージのビルドに関する設定
    build:
      # Dockerfileがあるディレクトリのパスを指定
      context: .
      dockerfile: Dockerfile
    # イメージ名を設定
    image: openfoam-v2012
    platform: linux/amd64
    stdin_open: true
    tty: true
    command: /bin/bash -c "source /usr/lib/openfoam/openfoam2012/etc/bashrc && \
             /usr/local/bin/copy_openfoam_tutorials.sh && \
             exec /bin/bash"
    
~~~

次に、OpenFOAMのコマンドを実行してくれるシェルスクリプトを作ります。
このシェルスクリプトで行いたいことは２点あります。
- 1点目：FOAM変数（OpenFOAMの変数）を用いてコンテナ内に作業用ディレクトリを作成する
- 2点目：コンテナ内の作業用ディレクトリにOpenFOAMのチュートリアルをコピーする

今回は、ローカル内の作業用ディレクトリをコンテナ内の作業用ディレクトリにバインドマウントしています。
→ ローカル内の作業用ディレクトリに「run/tutorials」フォルダが加わるイメージです。
```
# ローカル内の作業用ディレクトリに移動
$ cd $HOME/OpenFOAM

# copy_openfoam_tutorials.shファイルを作成する
$ touch copy_openfoam_tutorials.sh
```
シェルスクリプト（copy_openfoam_tutorials.sh）の中身はこんな感じにしました。

今回は「flamePropagationWithObstacles」はコピーしていません。
実はこのディレクトリ内に「0.orig/B」と「0.orig/b」が存在するのですが、Macでは大文字・小文字の区別をしてくれないのかな？、ちょっとややこしかったのでコピーしないようにしました。
（使用する予定も無いので、良いかな。。）
~~~md:copy_openfoam_tutorials.sh
#!/bin/bash

source /usr/lib/openfoam/openfoam2012/etc/bashrc

# 非ゼロの終了ステータスを返すとスクリプトの実行を停止する
set -e

# FOAM変数が使えるか確認
##################################
# -z 文字列が空のときtrue
if [ -z "$FOAM_RUN" ] ; then
  echo "エラー:FOAM_RUN" >&2
  exit 1
else
  echo "OK:FOAM_RUN"
fi

if [ -z "$FOAM_TUTORIALS" ] ; then
  echo "エラー:FOAM_TUTORIALS" >&2
  exit 1
else
  echo "OK:FOAM_TUTORIALS"
fi
##################################

# チュートリアルディレクトリのコピー
##################################
if [ -d "$FOAM_RUN/tutorials" ]; then
  echo "すでにFOAM_RUNディレクトリにtutorialsディレクトリがコピー作成されています"
else
  mkdir -p $FOAM_RUN
  rsync -a --exclude "$FOAM_TUTORIALS/combustion/PDRFoam/flamePropagationWithObstacles" "$FOAM_TUTORIALS" "$FOAM_RUN"
  echo "FOAM_RUNディレクトリにtutorialsディレクトリをコピーしました"
fi
##################################
~~~

コンテナを作成・実行してみる。

```
# イメージのビルドを行う
$ docker compose build

# コンテナの作成・実行
$ docker compose up -d

# 実行中のコンテナを一覧表示 
$ docker container ls
（一部抜粋）
CONTAINER ID   IMAGE
????????????   openfoam-v2012

# ログを確認する
$ docker logs <先ほどのコマンドで確認したCONTAINER ID>

OK:FOAM_RUN
OK:FOAM_TUTORIALS
FOAM_RUNディレクトリにtutorialsディレクトリをコピーしました
```

```
# コンテナに入る、コンテナ内で「bash」というシェルを立ち上げる
# 「myopenfoam」とは、compose.yamlファイルで定義したコンテナ名です。
$ docker compose exec myopenfoam /bin/bash
```
~~~md:コンテナ内
$ simpleFoam -help
(一部抜粋) 良さそう
Usage: simpleFoam [OPTIONS]
Options:
  -case <dir>       Specify case directory to use (instead of cwd)
~~~

OpenFOAMのインストールは上手くいっているようです。

# olaFlowをインストールする
この節では、OpenFOAMのライブラリであるolaFlowをインストールします。
方針としては、[こちら](https://openfoamwiki.net/index.php/Contrib/olaFlow#Tutorials)に記載しているolaFlowのインストール手順を踏まえて、Dockerfile、compose.ymlの修正、新たなシェルスクリプトの作成を行います。

Dockerfileは以下のようにしました。
前節との違いは大きく２点あります。
- 1.「git」をインストールするようにしました
- 2.olaFlowインストール用シェルスクリプトに関する記述を加えました

~~~md:Dockerfile
FROM opencfd/openfoam-default:2012
RUN apt update && \
  apt install  -y tree nano git
COPY copy_openfoam_tutorials.sh install_olaFlow.sh /usr/local/bin/
# スクリプトに実行権限を付与
RUN chmod +x /usr/local/bin/copy_openfoam_tutorials.sh \
  /usr/local/bin/install_olaFlow.sh
~~~

シェルスクリプト（install_olaFlow.sh）を用意しました。
中身はこのようにしました。
~~~md:install_olaFlow.sh
#!/bin/bash

source /usr/lib/openfoam/openfoam2012/etc/bashrc
# 非ゼロの終了ステータスを返すとスクリプトの実行を停止する
set -e

TEMP_DIR="$FOAM_RUN/../applications/utilities/olaFlow_temp"
if [ -d "$TEMP_DIR" ]; then
  echo "すでにolaFlowはインストール済みです"
else
  mkdir -p $TEMP_DIR
  cd $TEMP_DIR
  git clone https://github.com/phicau/olaFlow.git
  echo "olaFlowのコードをクローンしました"
  cd olaFlow
  echo "olaFlowをコンパイル中"
  ./allMake
  echo "olaFlowのコンパイルを終了しました"
  cp -r * $FOAM_RUN/../applications/utilities/olaFlow/
  echo "olaFlowのチュートリアルをコピーしました"
fi
~~~

compose.ymlには、シェルスクリプト（install_olaFlow.sh）用の記載を加えています。
変更箇所を以下に示しています。
~~~md:compose.ymlのvolumes部分
volumes:
      - /Users/<user_name>/OpenFOAM/run/:/root/OpenFOAM/-v2012/run/
      - /Users/<user_name>/OpenFOAM/olaFlow/:/root/OpenFOAM/-v2012/applications/utilities/olaFlow/tutorials
~~~
~~~md:compose.ymlのcommand部分
command: /bin/bash -c "source /usr/lib/openfoam/openfoam2012/etc/bashrc && \
            /usr/local/bin/copy_openfoam_tutorials.sh && \
            /usr/local/bin/install_olaFlow.sh && \
            exec /bin/bash"
~~~

コンテナを作成・実行してみる
```
$ docker compose build
$ docker compose up -d
$ docker logs <CONTAINER ID>
(途中省略)
olaFlowのコンパイルを終了しました
olaFlowのチュートリアルをコピーしました
```
これでコンパイルまで終了しました！

# olaFlowのチュートリアルを実行
本当に計算ができるか確認しましょう。
コンテナ内に入る
```
$ cd $HOME/OpenFOAM
$ docker compose exec myopenfoam /bin/bash
```

~~~md:コンテナ内
$ cd $FOAM_RUN/../applications/utilities/olaFlow/tutorials
$ tree -L 1
|-- CR35_dambreak
|-- README.md
|-- baseWaveFlume
|-- breakwater
|-- currentWaveFlume
|-- irreg45degTank
|-- oppositeSolitariesFlume
|-- pistonFlumeABS
|-- setOlaFlume
|-- waveFloatingObject
|-- wavemakerFlume
`-- wavemakerTank

# チュートリアルを1つコピーしました
$ cp -r baseWaveFlume mybaseWaveFlume
$ cd mybaseWaveFlume
~~~

今回は「system/controlDict」内でいくつか設定値を変更しました。
- endTime : 10
- deltaT : 0.01
- writeInterval : 0.1

また、「runCase」内の「rm -fr 0」、「cp -r 0.org 0」以外をコメントアウトしました。
~~~md:コンテナ内
$ ./runCase
$ blockMesh
$ setFields
$ olaFlow

# 計算終了後、.foamファイルを作る
$ touch aa.foam
~~~

ParaViewで可視化してみる。
![波1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3831763/80be6e47-61b7-fcbc-919a-62defb1e7adc.gif)



しっかりと造波できてますね。

もちろん、海岸構造物を設置してみたり、波高計を設置して水位変動の時系列データを取得することも可能です。
少し工夫すると、水理模型実験などで計測した水位変動の結果をもとに造波することも可能です。

# 最後に
macbook airで計算してみたけど、
もっと重たい計算をしてみたいのでAWSを使っていろいろ工夫したいなあ（勉強中）