SALMON TDDFTビルドの備忘録

# SALMONの概要
[ホーム |　SALMON (Scalable Ab-initio Light-Matter simulator for Optics and Nanoscience)](http://salmon-tddft.jp/jp/index.html)
実空間グリッドを使った物質と電磁波の相互作用を計算するコード。時間依存密度汎関数理論ベースの孤立(孤立境界条件)と固体(周期境界条件)の外場に対する実時間発展、またそれらが電磁波と結合した際の伝播が計算できる。

# SALMONのビルド
デフォルトではcmakeを使ったビルドが使われている。
公式インストールインストラクションはは[英語版](https://salmon-tddft.jp/webmanual/v_1_2_0/html/install_and_run.html)と[日本語版](https://salmon-tddft.jp/wiki/%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%A8%E5%AE%9F%E8%A1%8C)がある。

## cmakeを使ったビルド
### SALMON-v.2.2.0 on fjmpi 1.2.37 fj 1.2.37
東大情報基盤センターのWisteriaでの実行用バイナリのビルドを行う。

#### モジュールのロード
`module load odyssey`でFortranとMPIの環境をロード。
例えば、`module list`で以下が表示される。
```console
Currently Loaded Modulefiles:
 1) fjmpi/1.2.37   2) fj/1.2.37(default)   3) odyssey
```

#### cmake
[Install and Run &mdash; SALMON software manual v.2.2.0 documentation](https://salmon-tddft.jp/webmanual/current/html/install_and_run.html#build-and-install)によると、バージョンは3.14.0以降が必要とのことなので、`cmake --version`で確認すると
```console
cmake version 3.18.2

CMake suite maintained and supported by Kitware (kitware.com/cmake).
```
として、3.18.2なことが確認できた。

ディレクトリ`${SALMON_ROOT}/build`を作り、そのディレクトリに移動して`python ../configure.py --arch=fujitsu-a64fx-ea --prefix=../` [^1] を入力して以下の出力を得る(適宜改変):
```console
    $  cmake  -D CMAKE_TOOLCHAIN_FILE=fujitsu-a64fx-ea -D CMAKE_INSTALL_PREFIX=../ -D CMAKE_BUILD_TYPE=Release -D CMAKE_VERBOSE_MAKEFILE=off ..
-- The Fortran compiler identification is Fujitsu
-- The C compiler identification is Fujitsu
-- Detecting Fortran compiler ABI info
-- Detecting Fortran compiler ABI info - done
-- Check for working Fortran compiler: /opt/FJSVxtclanga/tcsds-1.2.37/bin/mpifrtpx - skipped
-- Checking whether /opt/FJSVxtclanga/tcsds-1.2.37/bin/mpifrtpx supports Fortran 90
-- Checking whether /opt/FJSVxtclanga/tcsds-1.2.37/bin/mpifrtpx supports Fortran 90 - yes
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /opt/FJSVxtclanga/tcsds-1.2.37/bin/mpifccpx - skipped
-- user-defined FFLAGS  =
-- user-defined CFLAGS  =
-- user-defined LDFLAGS =
-- Specific OpenMP flags: -Kopenmp -Nfjomplib
-- Specific Fortran preprocessor flags: -Cpp
-- Found MPI_C: /opt/FJSVxtclanga/tcsds-1.2.37/bin/mpifccpx (found version "3.1")
-- Found MPI_Fortran: /opt/FJSVxtclanga/tcsds-1.2.37/bin/mpifrtpx (found version "3.1")
-- Found MPI: TRUE (found version "3.1")
-- SALMON will uses the optimization by MPI version 3.
-- Performing Test FORTRAN_COMPILER_HAS_2MB_ALIGNED_ALLOCATION
-- Performing Test FORTRAN_COMPILER_HAS_2MB_ALIGNED_ALLOCATION - Success
-- Looking for unistd.h
-- Looking for unistd.h - found
-- Looking for stat
-- Looking for stat - found
-- Looking for access
-- Looking for access - found
-- Looking for mkdir
-- Looking for mkdir - found
-- Looking for nftw
-- Looking for nftw - found
-- Looking for remove
-- Looking for remove - found
-- Looking for PATH_MAX
-- Looking for PATH_MAX - found
-- Looking for __FUJITSU
-- Looking for __FUJITSU - found
-- Set vendor-specific LAPACK libraries: -SSL2BLAMP
-- testing command: MPIEXEC_EXECUTABLE-NOTFOUND -n 4 /home/hogehoge/work/opt/SALMON-v.2.2.0/build/salmon
-- Target executable file  = salmon
-- CMake generated FFLAGS  =  -Kopenmp -Nfjomplib  -Cpp   -SSL2BLAMP
-- CMake generated CFLAGS  =  -Kopenmp -Nfjomplib    -SSL2BLAMP
-- CMake generated LDFLAGS =
-- Configuring done
-- Generating done
-- Build files have been written to: /home/hogehoge/work/opt/SALMON-v.2.2.0/build
```
そして、`make`と`make install`で`${SALMON_ROOT}/bin/salmon`がビルドされる。

[^1]: 他の環境だと、たびたび`python`が`python3`にエイリアスされていないケースがある。その場合は`python3 ../configure.py --arch=fujitsu-a64fx-ea --prefix=../`にすれば、所望の動作が期待できる。

### SALMON-v.2.2.1 on Ubuntu 20.04
やっぱりGCCでビルドしたいじゃん。Makefileを直接つくのは結構面倒なことが分かってきたので、cmakeを使ってビルドする方法がキチンと[公式](https://salmon-tddft.jp/webmanual/v_2_2_1/html/install_and_run.html#build-by-gnu-compiler-collection-gcc)に記述がある。`--arch`を指定せず`FC`, `FFLAGS`, `CC`を指定してあげればよい。今回はUbuntu 20.04条で、cmakeのバージョンは3.16.3。
`${SALMON_ROOT}$`で`mkdir ./build & mv ./build`した後に、事前にビルドしてあった、gcc-11.4.0とそれをリンクしたopenmpi-5.0.3をenvironmental moduleでloadしてPATHを通した状態で以下のコマンドで通った。

```python:ビルド用コマンド
python3 ../configure.py --prefix=/opt_share/SALMON/2.2.1/openmpi-5.0.3_gcc-11.4.0 FC="gfortran" FFLAGS="-O3 -fallow-argument-mismatch" CC="gcc" --enable-mpi
make 
make install
```

`-fallow-argument-mismatch`は、[ここ](https://qiita.com/Yasushi-Shinohara/items/00acb97e55714d46b479#%E7%95%B0%E3%81%AA%E3%82%8B%E9%96%A2%E6%95%B0%E3%81%AE%E5%BC%95%E6%95%B0%E3%81%8C%E3%83%9E%E3%83%83%E3%83%81%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%81%A8%E6%80%92%E3%82%89%E3%82%8C%E3%82%8Bgcc-1140)で説明した最近のGCCで引数チェックがstrictになったことによって、古いコードが続々とエラーでビルド出来なくなった問題を解決するための処方箋。(本当はコードそのものをstrictに書いた方が良いが、自分で書いているコードでもない場合はこうしてしのぐほかない)

関連して作ったmodule用のファイルは以下の通り:
```
#%Module -*- tcl -*-
##
## dot module file
##
proc ModulesHelp { } {
        puts stderr "\tAdds SALMON to your environment variables.\n"
}

module-whatis   "adds SALMON to your environment variables"

set          moduleversion       2.2.1
set          root                /opt_share/SALMON/2.2.1/openmpi-5.0.3_gcc-11.4.0

module load openmpi/5.0.3/gcc-11.4.0

prepend-path PATH $root/bin
```

## GNU makeを使ったビルド

### SALMON-v.1.2.0 on mpich 3.3 GCC 4.8.5
個人的な趣味でGNU makeを使ったビルドを試みた。コードはSALMON-v.1.2.0で、mpich-3.3, gnu-4.8.5(CentOS 7.3.1611のパッケージ管理で入っている物)でビルド。

`gnu_makefiles/Makefile.gnu`をSALMON-v.1.2.0.tar.gzを展開して出てきたフォルダ(`$(SALMON_ROOT)`とする)の一番上の階層にコピー。

```bash
make -f ./Makefile.gnu
```
でビルド。`$(SALMON_ROOT)/bin`に`salmon.cpu`が出来る。

#### うまいことビルド出来ない問題

```
/usr/lib/ld: cannot find -llapack
/usr/lib/ld: cannot find -lblas
```
ある状態では上記のエラーが出てビルド出来なかった。
`ldconfig -p`でライブラリを探すと`liblapacke.so.3`と`liblapack.so.3`が見つかる。また、`/usr/lib64/`を見ると`liblapack.so.3.4.2`と`liblapacke.so.3.4.2`があるが、`-L/usr/lib64`を`Makefile.gnu`に追記しても、問題は解決しない。
ライブラリが足りないのかと考えて、ルートで

```bash
yum install lapack*
```
でdevel等も含めてインストールをした(依存関係のあるblasについてもインストールされる)ところ、ビルドが出来た。
この過程で入ったどのライブラリが本質的だったかはわからない。

### SALMON-v.1.1.0 openmpi-3.1.3 intel compiler-2019.3.199
コードはSALMON-v.1.1.0で、openmpi-3.1.3, intel-2019.3.199, CentOS 7.3.1611でビルド。

`gnu_makefiles/Makefile.intel-avx2`をSALMON-v.1.1.0.tar.gzを展開して出てきたフォルダ(`$(SALMON_ROOT)`とする)の一番上の階層にコピー。
この`Makefile`は、intel-MPIを前提に書かれているので、以下のように修正

```makefile
FC = mpif90
CC = mpicc
LIBLAPACK = -mkl=sequential
LIBSCALAPACK = -mkl=sequential
```
`make -f Makefile.intel-avx2`でビルド完了。
`$(SALMON_ROOT)/bin/salmon.cpu`が出来る。

### SALMON-v.2.0.1 on openmpi 3.1.3, intel-2019.3.199

```makefile:Makefile
# intel

TARGET = salmon
#FC = mpiifort
#CC = mpiicc
FC = mpif90
CC = mpicc
FFLAGS = -O3  -ansi-alias -fno-alias -fpp -nogen-interface -std03 -warn all
CFLAGS = -O3  -ansi-alias -fno-alias -Wall -restrict -std=c99
OMPFLAG = -qopenmp
MPIFLAG = -DUSE_MPI
SIMD_SET =

#LIBLAPACK = -mkl=cluster
LIBLAPACK = -mkl=sequential
# LIBLAPACK = -llapack -lblas

# LIBXC = -DUSE_LIBXC -lxcf90 -lxc -I"libxc_installed_dir/include" -L"libxc_installed_dir/lib"

CONFIG = \
    -DSYSTEM_HAS_POSIX \
    -DSYSTEM_HAS_POSIX_STAT \
    -DSYSTEM_HAS_POSIX_ACCESS \
    -DSYSTEM_HAS_POSIX_MKDIR \
    -DSYSTEM_HAS_STDIO_REMOVE \
    -DSYSTEM_HAS_POSIX_NFTW \
    -DSYSTEM_HAS_PATH_MAX_IN_LIMITS_H \
    -DSYSTEM_HAS_PATH_MAX_IN_LINUX_LIMITS_H
#    -DFORTRAN_COMPILER_HAS_2MB_ALIGNED_ALLOCATION \
#    -DUSE_OPT_DOMAIN_IS_POW2 \
#    -DUSE_OPT_ARRAY_PADDING \
#    -DUSE_OPT_SOFTWARE_PREFETCH \
#    -DFORTRAN_COMPILER_HAS_MPI_VERSION3 \
#    -DUSE_OPT_EXPLICIT_VECTORIZATION

MODULE_SWITCH = -module

ifneq (,$(wildcard make.body))
include make.body
else
include gnu_makefiles/make.body
endif
```

Libxcをリンクするときは、Libxc 4.3.4をインテルでビルドしたものを`/home/user/opt/libxc-4.3.4_intel`にインストールしたとすると、以下のように書き換えることでビルドできた。

```makefile
LIBXC = -DUSE_LIBXC -lxcf90 -lxc -I"/home/user/opt/libxc-4.3.4_intel/include" -L"/home/user/opt/libxc-4.3.4_intel/lib"
```
[Libxcビルドの備忘録 - Qiita](https://qiita.com/Yasushi-Shinohara/items/0621534abe6663ab8eca)にあるとおりintel-2019.3.199でビルドしようとすると、2021/05/27時点での最新盤の5.1.4ではうまくビルド出来なかった。そこで、4.3.4をここでは使うことにした。

# トラブルシューティング
## SALMON-v.1.1.0 openmpi-3.1.3 intel compiler-2019.3.199 がtorque-5.0.3で`qsub`すると走らない

標準出力で、`flag_nlcc = F`と書き出したところまで進んで、`forrtl: severe (174): SIGSEGV, segmentation fault occurred`を吐いて、落ちる。
同じ実行を普通のbashスクリプトで実行すると、普通に走る。

~~MPIをmpich-3.3, openmpi-4.0.0に替えて実行しても症状は同じ。~~
~~MPIを使わずシリアル実行してみても同じなので、MPIとの相性ではなく、torqueでのジョブ実行との相性の問題の可能性が高い。~~

~~試しにtorque経由の実行とbashスクリプトでの実行で、環境変数の差分をとって、`PATH`の部分は同じものを含むように変更してみたが、問題は解決せず。(2019/04/20)~~

端末、及びshellスクリプト経由で`ulimit -s`でスタックサイズをみると`unlimited`だったが、torque経由で投げると`8192`が設定されている。
torqueのジョブサブミットスクリプトに`ulimit -s unlimited`を追加したところ、openmpi-3.1.3については動いた。
スタックサイズが小さいので、大きな配列を宣言したところで、segmentation faultを吐いていたっぽい。
ただし、mpich-3.3では問題は解けていない。(2019/04/24)

## SALMON-v.1.2.1, Oakforest-PACS で標準入力のファイルの最後の文字列の後に改行がないと動かない
SALMON-v.1.2.1をOakforest-PACSでビルド(公式のインストールに手続きで`arch=intel-knl`を指定)して実行したところ、以下の個所まで標準出力に表示したまま、停止せずに計算が実行されなかった。

```
##############################################################################
# SALMON: Scalable Ab-initio Light-Matter simulator for Optics and Nanoscience
#
#                             Version 1.2.1
##############################################################################
  Libxc: [disabled]
```
原因は標準入力で読み込むファイルの最後の行(具体例では、以下の`/`の後)に改行がないことだった。

```
/
&analysis
  out_dos = 'y'
/
```
改行を入れることで期待通りに動くようになった。

但し、この改行は手元の環境(openmpi-3.1.3, intel compiler-2019.3.199, entOS 7.3.1611)では必須ではなかった。環境によっては、これでも動くようだが、基本的には改行を入れておいた方が良さげ。

## SALMON-v2.0.0でTBmBJを実行するとSCFの反復初期に大きな値が固有値に入っており、反復が進むにつれて値が大きくなっていってNaNになる

どうもデフォルト設定の初期値が悪いらしい。
以下のオプションを追加してSCFを回すとうまくいく。

```text
&scf
method_init_wf = "random"
/
```
## SALMON-v.2.2.0, AMD機で でAVX512のarchオプションをつけてビルドすると計算がエラーを吐いて終了する
### エラーを吐く実行バイナリの作り方:
`python3 ../configure.py --arch=intel-avx512 --prefix=../`
で`make`、`make install`でバイナリを準備する。
### 該当のエラー
```console
Please verify that both the operating system and the processor support Intel(R) X87, CMOV, MMX, FXSAVE, SSE, SSE2, SSE3, SSSE3, SSE4_1, SSE4_2, MOVBE, POPCNT, AVX, F16C, FMA, BMI, LZCNT, AVX2, AVX512F, AVX512DQ, ADX, AVX512CD, AVX512BW and AVX512VL instructions.
```

古いコアやAMDのコアは必ずしもAVX512の命令セットを実行できないので、一段階古い命令セットのAVX2を指定してビルドを試みる
`python3 ../configure.py --arch=intel-avx2 --prefix=../`
がこれもダメで、実はAMD EPYCについては、もっと明確なオプションが用意されている:
`python3 ../configure.py --arch=intel-avx2-epyc --prefix=../`

# 入力ファイルテンプレート
## SALMON-v1.2.1

```text:TBmBJ
&functional
  xc = 'TBmBJ'
/
```
```text:TBmBJ(c=1.0)
&functional
  xc = 'TBmBJ'
  cval = 1.0d0
/
```


```text:Linear_response
&emfield
  trans_longi = 'tr'
  ae_shape1 = 'impulse'
  epdir_re1 = 0., 0., 1.
/
```

```text:LASER_pulse
&emfield
  trans_longi = 'tr'
  ae_shape1 = 'Acos4'
  rlaser_int_wcm2_1 = 1d12
  pulse_tw1 = 1653.d0d0 !~ 40 fs
  omega1 = 0.05796d0    !~ 1.55 eV
  epdir_re1 = 0., 0., 1.
```

# 解析用コード
## SALMON-v1.2.1

```python:get_tAtEtJt.py
def get_tAtEtJt(fname, print_opt = False, plot_opt = True):
    f = open(fname,'r')
    lines = f.readlines()
    f.close()
    Nlen = len(lines)
    print(Nlen, ': No. of lines of the file, ',fname)
    #
    if (print_opt):
        for i in range(8):
            print(lines[i])
    #
    Nhead = 8
    Nt = Nlen - Nhead
    t = np.zeros(Nt, dtype='float64')
    At = np.zeros([Nt,3], dtype='float64')
    Et = np.zeros([Nt,3], dtype='float64')
    Jt = np.zeros([Nt,3], dtype='float64')
    for i in range(Nt):
        temp = lines[Nhead + i].split()
        t[i] = temp[0]
        At[i,0] = temp[ 7]
        At[i,1] = temp[ 8]
        At[i,2] = temp[ 9]
        Et[i,0] = temp[10]
        Et[i,1] = temp[11]
        Et[i,2] = temp[12]
        Jt[i,0] = temp[13]
        Jt[i,1] = temp[14]
        Jt[i,2] = temp[15]
    if (plot_opt):
        plt.figure()
        plt.plot(t*Atomtime,Jt[:,0],label='Jx')
        plt.plot(t*Atomtime,Jt[:,1],label='Jy')
        plt.plot(t*Atomtime,Jt[:,2],label='Jz')
        plt.legend()
        plt.grid()
        plt.show()    
    return t, At, Et, Jt
#
fname = '/home/shinohara/hoge/Ghogehoge_rt.data'
t, At, Et, Jt = get_tAtEtJt(fname)
```