FrontISTR 5.0 のコンパイル方法 (Intel MKL + Intel MPI版)

# FrontISTR 5.0 のコンパイル(Intel MKL + Intel MPI版)

## はじめに

FrontISTR 5.0をIntel MKLとIntel MPIを使ったインストール方法を説明します。

FrontISTRは、[FrontISTR-Commons](https://www.frontistr.com/)で開発が進められている、有限要素法の構造解析プログラムです。

UbuntuとCentOSで手順が違う箇所は別々に記述します。

また、[公式ダウンロードサイト](https://www.frontistr.com/download/) からは docker イメージや Windows10用のバイナリもダウンロードすることが出来ます。面倒な方はこちらをご利用ください。

その他のインストール方法や使い方は、[公式マニュアル](https://frontistr-commons.gitlab.io/FrontISTR/manual_ja/index.html) がありますので、こちらも参考にして下さい。

## 準備

### バイナリパッケージのインストール (Ubuntu 18.04の場合)

```
$ sudo apt install build-essential curl cmake gfortran
```

### バイナリパッケージのインストール(CentOS7.7の場合)

```
$ sudo yum groupinstall "Development Tools"
```

```
$ sudo yum install cmake
```

ただし、yum でインストールされる cmake のバージョンが古いため、Trilinosがコンパイル出来ません。[https://www.cmake.org](https://www.cmake.org/) から最新版バイナリをダウンロードできますので、そちらの利用をお勧めします。

### Intel プロダクトのインストール (Ubuntu18.04の場合)

Intel MKL/MPI は、サポートが無いバージョンを利用します。
また、簡単のためIntelで用意されている Ubuntu 用 DEB パッケージをインストールします。

```
$ curl -O https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB
$ apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB
```

```
$ curl -O https://apt.repos.intel.com/setup/intelproducts.list -o /etc/apt/sources.list.d/intelproducts.list
$ sudo apt update
```

してから

```
$ sudo apt install intel-mkl
```

と入力すると、現在サポートされている仮想パッケージの候補が表示されます。

```
パッケージ intel-mkl は、以下によって提供される仮想パッケージです:
  intel-mkl-2019.5-075 2019.5-075
  intel-mkl-2019.4-070 2019.4-070
  intel-mkl-2019.3-062 2019.3-062
  intel-mkl-2019.2-057 2019.2-057
  intel-mkl-2019.1-053 2019.1-053
  intel-mkl-2019.0-045 2019.0-045
  intel-mkl-2018.4-057 2018.4-057
  intel-mkl-2018.3-051 2018.3-051
  intel-mkl-2018.2-046 2018.2-046
  intel-mkl-2018.1-038 2018.1-038
  intel-mkl-2018.0-033 2018.0-033
インストールするには、明示的にいずれかを選択する必要があります。

E: パッケージ 'intel-mkl' にはインストール候補がありません
```

この中でインストールしたい仮想パッケージを選択し、インストールします。この時点での最新版をインストールしてみましょう。

```
$ sudo apt install intel-mkl-2019.5-075
```

同様な手順で intel-mpi もインストールします。念のためintel-mklと同じリビジョンのものをインストールします。

```
$ sudo apt install intel-mpi
パッケージ intel-mpi は、以下によって提供される仮想パッケージです:
  intel-mpi-2019.6-085 2019.6-085
  intel-mpi-2019.5-075 2019.5-075
  intel-mpi-2019.4-070 2019.4-070
  intel-mpi-2019.3-062 2019.3-062
  intel-mpi-2019.2-057 2019.2-057
  intel-mpi-2019.1-053 2019.1-053
  intel-mpi-2019.0-045 2019.0-045
  intel-mpi-2018.4-057 2018.4-057
  intel-mpi-2018.3-051 2018.3-051
  intel-mpi-2018.2-046 2018.2-046
インストールするには、明示的にいずれかを選択する必要があります。

E: パッケージ 'intel-mpi' にはインストール候補がありません
$ sudo apt install intel-mpi-2019.5-075
```

### Intel プロダクトのインストール(CentOS7の場合)

また、簡単のためIntelで用意されている RedHat 用 RPM パッケージをインストールします。

```
$ sudo yum-config-manager --add-repo https://yum.repos.intel.com/setup/intelproducts.repo
$ sudo rpm --import https://yum.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB
```

Intel-MKLとIntel-MPIを同時に使う場合、バージョン番号が一致している必要があるようなので、バージョン番号を明示してインストールします。

```
$ sudo yum install intel-mkl-2018.4
$ sudo yum install intel-mpi-2018.4
```

### コンパイル環境の設定と確認

ここからの手順は Ubuntu/CentOS 共に同じです。
Intel MKLやIntel MPIを利用する前に以下のシェルスクリプトを実行してください。

```
$ source /opt/intel/bin/compilervars.sh intel64
```

```
$ source /opt/intel/compilers_and_libraries/linux/mpi/intel64/bin/mpivars.sh intel64
```

環境設定が出来たか確認してください。

```
$ echo $I_MPI_ROOT
/opt/intel/compilers_and_libraries_2019.5.281/linux/mpi
```

```
$ echo $MKLROOT
/opt/intel/compilers_and/libraries_2019.5.281/linux/mkl
```

以上の環境変数が設定されていれば、コンパイルの準備は完了です。

## コンパイル

### ライブラリのダウンロード

FrontISTRをコンパイルするには、以下のライブラリが必要になります。

| 名前 | ダウンロード先 |
|------|--------------|
| FrontISTR_V50.tar.gz 	        | https://www.frontistr.com/ |
| REVOCAP_Refiner-1.1.04.tar.gz | http://www.frontistr.com/  |
| metis-5.1.0.tar.gz 	        | http://glaros.dtc.umn.edu/gkhome/metis/metis/download |
| MUMPS_5.1.2.tar.gz 	        | http://mumps.enseeiht.fr/ |
| Trilinos-trilinos-12.18.1-release-12-18-1.zip  | https://github.com/trilinos/Trilinos/tree/trilinos-release-12-18-1 の 「Download ZIP」から |

LAPACK, ScaLAPACKは、バイナリでインストールした MKL パッケージに入っていますので、これを利用します。

ダウンロードしたファイルは `$HOME/work` へ保存し、コンパイルします。

また、コンパイルしたライブラリを `$HOME/local` 以下にコピーするためディレクトリを作成しておきます。

また、MKLを導入することにより 

```
!SOLVER, METHOD=MKL
```

と指定して、MUMPS以外の直接法ソルバーを使うことが出来るようになります。

```
$ cd $HOME
$ mkdir -p local/bin
$ mkdir local/include
$ mkdir local/lib
$ export PATH=$HOME/local/bin:$PATH
```

### REVOCAP_Refiner のコンパイル

```
$ tar xvf REVOCAP_Refiner-1.1.04.tar.gz
$ cd REVOCAP_Refiner-1.1.04
$ make
$ cp lib/x86_64-linux/libRcapRefiner.a $HOME/local/lib
$ cp Refiner/rcapRefiner.h $HOME/local/include
```

### Metisのコンパイル

```
$ cd $HOME/work
$ tar xvf metis-5.1.0.tar.gz
$ cd metis-5.1.0
$ make config prefix=$HOME/local cc=gcc openmp=1
$ make
$ make install
```

### MUMPSのコンパイル

インテル用のテンプレートを、`Makefile.inc` としてコピーします。

```
$ cd $HOME/work
$ tar xvf MUMPS_5.1.2.tar.gz
$ cd MUMPS_5.1.2
$ cp Make.inc/Makefile.INTEL.PAR Makefile.inc
```

コピーした `Makefile.inc` gcc/Intel MKL/Intel MPI用に編集します。

```
LMETISDIR  = $(HOME)/local
IMETIS     = -I$(LMETISDIR)/include

LMETIS     = -L$(LMETISDIR)/lib

ORDERINGSF = -Dprod -Dmetis

CC = mpigcc
FC = mpifc
FL = mpifc

LIBOTHERS = -liomp5 -lpthread

OPTF    = -O3 -DBLR_MT -fopenmp -DGEMM_AVAILABLE
OPTL    = -O3 -fopenmp
OPTC    = -O3 -I. -fopenmp
```

編集が済んだらコンパイルし、ライブラリ/ヘッダを `$HOME/local` 以下へコピーします。

```
$ make
$ cp lib/*.a $HOME/local/lib
$ cp include/*.h $HOME/local/include
```

### Trilinosのコンパイル

```
$ unzip Trilinos-trilinos-12.18.1-release-12-18-1.zip
$ cd Trilinos-trilinos-release-12-18-1
```

```
$ mkdir build
$ cd build
$ cmake \
        -DCMAKE_INSTALL_PREFIX=$HOME/local \
        -DCMAKE_C_COMPILER=mpigcc \
        -DCMAKE_CXX_COMPILER=mpigxx \
        -DCMAKE_Fortran_COMPILER=mpifc \
        -DTPL_ENABLE_MPI=ON \
        -DTPL_ENABLE_LAPACK=ON \
        -DTPL_ENABLE_SCALAPACK=ON \
        -DTPL_ENABLE_METIS=ON \
        -DTPL_ENABLE_MUMPS=ON \
        -DTrilinos_ENABLE_ML=ON \
        -DTrilinos_ENABLE_Zoltan=ON \
        -DTrilinos_ENABLE_OpenMP=ON \
        -DTrilinos_ENABLE_Amesos=ON \
        -DTrilinos_ENABLE_ALL_OPTIONAL_PACKAGES=OFF \
        -DTPL_ENABLE_MKL=ON \
        -DTPL_ENABLE_PARDISO_MKL=ON \
        -DMKL_INCLUDE_DIRS="${MKLROOT}/include" \
        -DMKL_LIBRARY_DIRS="${MKLROOT}/lib/intel64" \
        -DPARDISO_MKL_INCLUDE_DIRS="${MKLROOT}/include" \
        -DPARDISO_MKL_LIBRARY_DIRS="${MKLROOT}/lib/intel64" \
        -DAmesos_ENABLE_PARDISO_MKL=ON \
        -DMKL_INCLUDE_DIRS="${MKLROOT}/include" \
        -DMKL_LIBRARY_DIRS="${MKLROOT}/lib/intel64" \
        -DPARDISO_MKL_INCLUDE_DIRS="${MKLROOT}/include" \
        -DPARDISO_MKL_LIBRARY_DIRS="${MKLROOT}/lib/intel64" \
        -DAmesos_ENABLE_PARDISO_MKL=ON \
        -DBLAS_LIBRARY_DIRS="${MKLROOT}/lib/intel64" \
        -DLAPACK_LIBRARY_DIRS="${MKLROOT}/lib/intel64" \
        -DSCALAPACK_LIBRARY_DIRS="${MKLROOT}/lib/intel64" \
        -DBLAS_LIBRARY_NAMES="mkl_intel_lp64;mkl_gnu_thread;mkl_core" \
        -DLAPACK_LIBRARY_NAMES="mkl_intel_lp64;mkl_gnu_thread;mkl_core" \
        -DSCALAPACK_LIBRARY_NAMES="mkl_scalapack_lp64;mkl_blacs_intelmpi_lp64" \
        ..
$ make
$ make install
```

### FrontISTRのコンパイル

```
$ tar xvf FrontISTR.tar.gz
$ cd FrontISTR
$ mkdir build
$ cd build
$ cmake \
    -DCMAKE_INSTALL_PREFIX=$HOME/local \
    -DCMAKE_PREFIX_PATH=$HOME/local \
    -DCMAKE_C_COMPILER=gcc \
    -DCMAKE_CXX_COMPILER=g++ \
    -DCMAKE_Fortran_COMPILER=gfortran \
    -DBLAS_LIBRARIES="${MKLROOT}/lib/intel64/libmkl_intel_lp64.so;${MKLROOT}/lib/intel64/libmkl_gnu_thread.so;${MKLROOT}/lib/intel64/libmkl_core.so" \
    -DLAPACK_LIBRARIES="${MKLROOT}/lib/intel64/libmkl_intel_lp64.so;${MKLROOT}/lib/intel64/libmkl_gnu_thread.so;${MKLROOT}/lib/intel64/libmkl_core.so" \
    -DSCALAPACK_LIBRARIES="${MKLROOT}/lib/intel64/libmkl_scalapack_lp64.so;${MKLROOT}/lib/intel64/libmkl_intel_lp64.so;${MKLROOT}/lib/intel64/libmkl_gnu_thread.so;${MKLROOT}/lib/intel64/libmkl_core.so;${MKLROOT}/lib/intel64/libmkl_blacs_intelmpi_lp64.so;iomp5;pthread;m;dl" \
    -DWITH_MKL=1 \
    ..

$ make -j4
$ make install
```

`$(HOME)/local/bin` へ FrontISTR `fistr1` がインストールされます。

念のため、各ダイナミックリンクライブラリーが正しいものをリンクしているかを確認してください。

```
$ ldd fistr1
	linux-vdso.so.1 (0x00007fff48547000)
	libmkl_intel_lp64.so => /opt/intel/compilers_and_libraries_2019.5.281/linux/mkl/lib/intel64_lin/libmkl_intel_lp64.so (0x00007f254ed3d000)
	libmkl_scalapack_lp64.so => /opt/intel/compilers_and_libraries_2019.5.281/linux/mkl/lib/intel64_lin/libmkl_scalapack_lp64.so (0x00007f254e435000)
	libmkl_blacs_intelmpi_lp64.so => /opt/intel/compilers_and_libraries_2019.5.281/linux/mkl/lib/intel64_lin/libmkl_blacs_intelmpi_lp64.so (0x00007f254e1f3000)
	libmkl_gnu_thread.so => /opt/intel/compilers_and_libraries_2019.5.281/linux/mkl/lib/intel64_lin/libmkl_gnu_thread.so (0x00007f254c91a000)
	libmkl_core.so => /opt/intel/compilers_and_libraries_2019.5.281/linux/mkl/lib/intel64_lin/libmkl_core.so (0x00007f25485e9000)
	libiomp5.so => /opt/intel/compilers_and_libraries_2019.5.281/linux/compiler/lib/intel64_lin/libiomp5.so (0x00007f25481f4000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f2547fd5000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f2547c37000)
	libmpifort.so.12 => /opt/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/lib/libmpifort.so.12 (0x00007f2547879000)
	libmpi.so.12 => /opt/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/lib/release/libmpi.so.12 (0x00007f2546874000)
	libgfortran.so.4 => /usr/lib/x86_64-linux-gnu/libgfortran.so.4 (0x00007f2546495000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f254627d000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2545e8c000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f255088a000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f2545b03000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f25458ff000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f25456f7000)
	libfabric.so.1 => /opt/intel/compilers_and_libraries_2019.5.281/linux/mpi/intel64/libfabric/lib/libfabric.so.1 (0x00007f25454bf000)
	libquadmath.so.0 => /usr/lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007f254527f000)
```

以上で FrontISTR 5.0のインストールは完了です。

## テスト

最初に、チュートリアルを実行してみましょう。

### OpenMP並列(共有メモリスレッド並列)

スレッド並列の問題を実行してみます。

CPUは4コアあり、4スレッド並列実行をする場合、

```
$ cd FrontISTR/tutorial/01_elastic_hinge
$ fistr1 -t 4
```
のようになります。

`-t` の後にスペースを空けて並列数を整数で指定します。

![hinge_openmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81482/483f7143-61b3-b0a2-ab1b-85e9a1897ceb.png)

OpenMP並列で解析した結果。Paraviewで生成したVTKファイルのNodalMISESを表示し、変位は50倍に強調しました。

### MPI並列(分散メモリプロセス並列)

複数のマシン間で並列実行する場合、MPI並列を使うことが有ります。
FrontISTRの場合、メッシュファイルを予め分割して計算をします。

```
$ cd FrontISTR/tutorial/02_elastic_hinge_parallel
$ hecmw_part1
```

分割されたら、mpirunでFrontISTRをMPIプロセスとして起動します。

```
$ mpiexec -np 4 fistr1 -t 1
```

上記のコマンドラインは、MPIプロセスを4、各マシンで1スレッドと指定しています。

![hinge_mpi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81482/1c430741-5466-5512-5349-1455b640fe58.png)

MPI並列で解析した結果。Paraviewで生成したVTKファイルのNodalMISESを表示し、変位は50倍に強調しました。