FrontISTR v5.0 を RHEL/CentOS 7.x (等)でcmakeを使ってビルドして動かす手順


細かいことは抜きにして、最も手っ取り早く、かつなるべく高機能に動かすことを前提に作成しています。

v4.6でしたら以下の記事も参考になります。
[オープンソース大規模並列FEM非線形構造解析プログラム FrontISTR v4.6のインストール (CentOS 7.3)
](https://qiita.com/michioga/items/54220e6d62b06acba2d4)

※ RHEL7 としていますが、パッケージマネージャとしてyumを使うLinux環境だとほとんど同じと思います。


# ビルド環境及び並列計算の構築 (パッケージ)

この部分は、パッケージを使うべきではべきではない、Superuserは使うななどの後述の記述とは整合しないのですが、gccやcmakeはビルド環境として、通常のスーパーコンピュータやクラスタでは用意されているはずであることを前提として考えます。

```
sudo yum -y groupinstall "Development Tools"
sudo yum -y install cmake ruby
sudo yum -y install epel-release
sudo yum -y install openmpi openmpi-devel
```
※ openmpiについてはなくても、逐次計算版として動かせます。

CentOSでは、MPIの環境変数をenvironmental-modulesで設定するため読み込み直し、以下のように、自動的に環境変数が設定されるようにしておくと便利です。

```
. /etc/profile.d/modules.sh 
echo 'module add mpi/openmpi-x86_64' >> ~/.bash_profile
. ~/.bash_profile
```

epelにあるopenmpiのバージョンが古いので必要に応じて新しいバージョンのOpenMPIをご利用下さい。



# FrontISTRをコンパイルとインストール

一部のパッケージは、リポジトリから取ってきてインストールすることもできますが、
Ubuntuと比較して全部は入らず一部だけであること、スーパーユーザ権限がもらえない共用計算機環境で動かす事例は多いはずであることを前提として非推奨として下部に記載しております。


## Recomend* パッケージを使わずに、オプショナルライブラリを用意して入れる方法

必要なライブラリを、ユーザのローカルに入れておくということは、一般に(少なくとも計算科学分野では)よく行われます。
そこで、必要なライブラリを自力で手っ取り早くコンパイルする参考になるスクリプト例を記載します。

MPIだけを、環境側で用意しておけば他のライブラリは自力でコンパイルして用意することができます。
※MPIは、特に複数ノードシステムの場合、ハードウェアや構成を考慮する必要もあり、一般にこうすれば良いというと書けません。

なお、MUMPSはCeCILLライセンスを公称しているので、再配布が許されるはずです。再配布された場合と同様(登録をしなくても入手できる)という考えのもと、公式への直リンクを貼っています。
[MUMPS公式サイト](http://mumps.enseeiht.fr/)では、登録を求めておりますので、登録をしていただければ幸いです。


```
BUILD_ROOT=`pwd`
LIB_ROOT=${HOME}/.local
# END modify.

mkdir -p ${LIB_ROOT}/bin ${LIB_ROOT}/lib ${LIB_ROOT}/include
export PATH=${LIB_ROOT}/bin:$PATH


########################################
# OpenBLAS
########################################
git clone -b v0.3.7 --depth=1 https://github.com/xianyi/OpenBLAS.git
cd OpenBLAS
make -j DYNAMIC_ARCH=1 USE_OPENMP=1 BINARY=64 NO_SHARED=1
make PREFIX=${LIB_ROOT} install
cd ${BUILD_ROOT}

########################################
# metis-5.1.0
########################################
curl -L -O http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/metis-5.1.0.tar.gz
tar xvf metis-5.1.0.tar.gz
cd metis-5.1.0
make config prefix=${LIB_ROOT} cc=gcc openmp=1 shared=not-set
make install -j4
cd ${BUILD_ROOT}

########################################
# scalapack-2.1.0
########################################
git clone -b v2.1.0 --depth=1 https://github.com/Reference-ScaLAPACK/scalapack
cd scalapack
mkdir build
cd build
cmake \
  -DBUILD_SHARED_LIBS=OFF \
  -DBUILD_STATIC_LIBS=ON \
  -DCMAKE_INSTALL_PREFIX=${LIB_ROOT} \
  -DCMAKE_EXE_LINKER_FLAGS="-fopenmp" \
  -DBLAS_LIBRARIES=$LIB_ROOT/lib/libopenblas.a \
  -DLAPACK_LIBRARIES=$LIB_ROOT/lib/libopenblas.a \
  ..
make -j
make install
cd ${BUILD_ROOT}

########################################
# MUMPS-5.3.3
########################################
curl -L -O http://mumps.enseeiht.fr/MUMPS_5.3.3.tar.gz
tar xvf MUMPS_5.3.3.tar.gz
cd MUMPS_5.3.3
cp Make.inc/Makefile.inc.generic Makefile.inc
sed -i \
  -e "s|^#LMETISDIR = .*$|LMETISDIR = ${LIB_ROOT}|" \
  -e "s|^#IMETIS    = .*$|IMETIS = -I\$(LMETISDIR)/include|" \
  -e "s|^#LMETIS    = -L\$(LMETISDIR) -lmetis$|LMETIS = -L\$(LMETISDIR)/lib -lmetis|" \
  -e "s|^ORDERINGSF  = -Dpord$|ORDERINGSF = -Dpord -Dmetis|" \
  -e "s|^CC      = cc|CC      = mpicc|"  \
  -e "s|^FC      = f90|FC      = mpif90|"  \
  -e "s|^FL      = f90|FL      = mpif90|" \
  -e "s|^LAPACK = -llapack|LAPACK = -L${LIB_ROOT}/lib -lopenblas|" \
  -e "s|^SCALAP  = -lscalapack -lblacs|SCALAP  = -L${LIB_ROOT}/lib -lscalapack|" \
  -e "s|^LIBBLAS = -lblas|LIBBLAS = -L${LIB_ROOT}/lib -lopenblas|" \
  -e "s|^OPTF    = -O|OPTF    = -O -fopenmp|" \
  -e "s|^OPTC    = -O -I\.|OPTC    = -O -I. -fopenmp|" \
  -e "s|^OPTL    = -O|OPTL    = -O -fopenmp|" Makefile.inc
make d s c z -j
cp include/*.h ${LIB_ROOT}/include
cp lib/*.a ${LIB_ROOT}/lib
cd ${BUILD_ROOT}

########################################
# Trilinos 12.12.1
########################################
git clone -b trilinos-release-12-12-1 --depth=1 https://github.com/trilinos/Trilinos.git
cd Trilinos

mkdir build
cd build
cmake \
  -DCMAKE_INSTALL_PREFIX=${LIB_ROOT} \
  -DCMAKE_C_COMPILER=mpicc \
  -DCMAKE_CXX_COMPILER=mpicxx \
  -DCMAKE_Fortran_COMPILER=mpif90 \
  -DTPL_ENABLE_LAPACK=ON \
  -DTPL_ENABLE_SCALAPACK=ON \
  -DTPL_ENABLE_METIS=ON \
  -DTPL_ENABLE_MUMPS=ON \
  -DTPL_ENABLE_MPI=ON \
  -DTrilinos_ENABLE_ML=ON \
  -DTrilinos_ENABLE_Zoltan=ON \
  -DTrilinos_ENABLE_OpenMP=ON \
  -DTrilinos_ENABLE_Amesos=OFF \
  -DTrilinos_ENABLE_ALL_OPTIONAL_PACKAGES=OFF \
  -DMETIS_LIBRARY_DIRS=$LIB_ROOT/lib \
  -DMUMPS_LIBRARY_DIRS=$LIB_ROOT/lib \
  -DBLAS_LIBRARY_DIRS=$LIB_ROOT/lib \
  -DLAPACK_LIBRARY_DIRS=$LIB_ROOT/lib \
  -DSCALAPACK_LIBRARY_DIRS=$LIB_ROOT/lib \
  -DBLAS_LIBRARY_NAMES="openblas" \
  -DLAPACK_LIBRARY_NAMES="openblas" \
  ..
make -j
make install
cd ${BUILD_ROOT}

########################################
# REVOCAP_Refiner
########################################
#git clone https://gitlab.com/FrontISTR-Commons/REVOCAP_Mesh.git
git clone --depth=1 https://github.com/FrontISTR/REVOCAP_Mesh.git
cd REVOCAP_Mesh
make -j Refiner
find lib -type f -name "libRcapRefiner*" -exec cp {} ${LIB_ROOT}/lib/ \;
find . -type f -name "rcapRefiner.h" -exec cp {} ${LIB_ROOT}/include/ \;
cd ${BUILD_ROOT}

########################################
# FrontISTR
########################################
#git clone https://gitlab.com/FrontISTR-Commons/FrontISTR.git
git clone --depth=1 https://github.com/FrontISTR/FrontISTR.git
cd FrontISTR
mkdir build; cd build
cmake \
  -DCMAKE_INSTALL_PREFIX=${LIB_ROOT} \
  -DBLAS_LIBRARIES=${LIB_ROOT}/lib/libopenblas.a \
  -DLAPACK_LIBRARIES=${LIB_ROOT}/lib/libopenblas.a \
  ..
make -j
make install

```

## non-recommended* パッケージを使ったやり方

通常，並列計算機環境としては行うことはしませんが，手元のPCやDocker imageを作る際などには役に立つかもしれません。
 
### パッケージのダウンロード
CentOSの場合、パッケージを使用して、Trilinosは使えません。
cmakeのサーチがうまく行かず、cmakeオプションで色々と指定しないといけません。


```
sudo yum -y install metis metis-devel MUMPS MUMPS-devel
sudo yum -y install openblas openblas-devel scalapack-openmpi scalapack-openmpi-devel
```

### ユーザローカルバイナリとしてインストール
通常、共用計算機を前提とする科学技術計算のプログラムは、ユーザフォルダ内で完結させることが推奨されるので、スーパーユーザ権限を使うことはやらないことが多いです。
ということで、RHEL系でもDebian系でも共通して使えるよう（つまり余計なことをしなくてもパスが通っているように）、~/.local/binにインストールしてみましょう。
(※ 「~/」 はユーザのホームディレクトリを表しています。)

```
git clone https://github.com/FrontISTR/FrontISTR
cd FrontISTR/; mkdir build; cd build
cmake -DCMAKE_INSTALL_PREFIX=~/.local \
      -DBLAS_goto2_LIBRARY=/usr/lib64/libopenblas.so \
      -DLAPACK_goto2_LIBRARY=/usr/lib64/libopenblas.so \
      -DMETIS_INCLUDE_PATH=/usr/include \
      -DMETIS_LIBRARIES=/usr/lib64/libmetis.so \
      -DMUMPS_INCLUDE_PATH=/usr/include/MUMPS \
      -DMUMPS_LIBRARIES=/usr/lib64/libdmumps.so \
      -DSCALAPACK_LIBRARIES=/usr/lib64/openmpi/lib/libscalapack.so \
      ../
make -j 16
make install 
```

### システム共通バイナリとしてインストール
/usr/local/binにバイナリを配置する場合。システム共通バイナリを作る場合、自分のローカルコンピュータに閉じている場合ならばこのような使い方もあります。

```
git clone https://github.com/FrontISTR/FrontISTR
cd FrontISTR/; mkdir build; cd build
cmake -DCMAKE_INSTALL_PREFIX=~/.local \
      -DBLAS_goto2_LIBRARY=/usr/lib64/libopenblas.so \
      -DLAPACK_goto2_LIBRARY=/usr/lib64/libopenblas.so \
      -DMETIS_INCLUDE_PATH=/usr/include \
      -DMETIS_LIBRARIES=/usr/lib64/libmetis.so \
      -DMUMPS_INCLUDE_PATH=/usr/include/MUMPS \
      -DMUMPS_LIBRARIES=/usr/lib64/libdmumps.so \
      -DSCALAPACK_LIBRARIES=/usr/lib64/openmpi/lib/libscalapack.so \
      ../
make -j 16
sudo make install 
```


#MPIとOpenMP同時有効時の注意事項

この方法でできた実行ファイルは、OpenMPとMPIの双方の並列化機能が、有効になっています。
このために、コア数分をMPI実行すると、OpenMPのスレッドも同様に起動してしまい、極めて低速になるので注意して下さい。

※ デフォルトでOpenMPプロセスは、コア数分の$n$プロセス生成されます。ここで、MPIプロセスを$n$で起動すると、$n^2$のプロセスが、$n$個のコアを取り合い、遅くなります。


対策1. フラットMPI: 以下のようにOpenMPスレッドは1にして実行する。

```
mpirun -np 16 -x OMP_NUM_THREADS=1 fistr1
```

対策2: OpenMPによるスレッド並列

```
fistr1
```

一般に、FrontISTRでは、特に並列数が大きくなると、フラットMPIのほうが早く計算できることが多いです。
※ MPI並列で動作させる場合は、事前にパーティショニングが必要です。

なお、このことを考慮したくないということであれば、-DWITH_OPENMP=OFFのオプションで、FrontISTRをコンパイルして、フラットMPIのみで使うのも良いでしょう。