はじめてのLAMMPS


## インストール方法

Homebrewを用いる. 

Homebrewのインストールはネットで調べると簡単にできる.

その上でターミナルに以下を実行.

```zsh
brew install lammps
```

`/opt/homebrew/share/lammps/examples/` にLAMMPSのサンプルが入っていれば成功.

## 実行してみよう

とりあえず実行をするには, 以下のコマンドをLAMMPSファイルのディレクトリ上で走らせる.

※LAMMPSファイルは「in.」 が接頭についている.

```zsh
mpirun -n 4 lmp_mpi -log output.log -in in.logo
```

私はLAMMPSの実行によって, 拡張子がそれぞれ, 「.log」「.lammpstrj」「.yaml」の3つのファイルを出力するようにしている. 

- .log : 実験ログの確保のために出力. 
  - これのタイトルと同一の出力ファイルがもともとどのような系の設定から生まれたものなのかを確認するためにマストで出力している. 
  - 計算時間も下の方に記載される.
- .lammpstrj : VMDで系の動きを確認するのに使用する. 
  - データサイズが大きくなるので注意が必要.
- .yaml : データ分析をする際, 各物理量を取得するのに重宝. 



## 例として使用するファイル

- in.logo
  - [LAMMPS公式サイト](https://www.lammps.org/#gsc.tab=0)にあるファイル(input script).

```lammps:in.logo
# LAMMPSロゴのシミュレーション


units		lj  # LJ単位系.
atom_style	atomic  # 粒子.
dimension	2   # 次元.

lattice		sq2 0.5 origin 0.25 0.25 0.0  # 粒子の初期配置.
region		box block 0 31 0 7 -0.5 0.5 # 系の領域設定.
create_box	2 box    # 系の生成.
create_atoms	1 box   # 粒子の生成.

# LAMMPSロゴの各文字に対応する領域を定義
# 各領域は文字を形成する原子のサブセットを定義
region	        L1 block 2 3 1 6 -0.5 0.5
region	        L2 block 2 5 1 2 -0.5 0.5
region		L union 2 L1 L2

# 文字領域内の原子はタイプ2
set		region L type 2

# A, M(1M, 2M), P, Sの文字に対応する類似の領域が定義されている

region	        A1 block 6 7 1 6 -0.5 0.5
region	        A2 block 8 9 1 6 -0.5 0.5
region	        A3 block 6 9 3 4 -0.5 0.5
region	        A4 block 6 9 5 6 -0.5 0.5
region		A union 4 A1 A2 A3 A4

region	        1M1 block 10 11 1 6 -0.5 0.5
region	        1M2 block 14 15 1 6 -0.5 0.5
region	        1M3 block 10 15 5 6 -0.5 0.5
region	        1M4 block 12 13 3 6 -0.5 0.5
region		1M union 4 1M1 1M2 1M3 1M4

region	        2M1 block 16 17 1 6 -0.5 0.5
region	        2M2 block 20 21 1 6 -0.5 0.5
region	        2M3 block 16 21 5 6 -0.5 0.5
region	        2M4 block 18 19 3 6 -0.5 0.5
region		2M union 4 2M1 2M2 2M3 2M4

region	        P1 block 22 23 1 6 -0.5 0.5
region	        P2 block 24 25 3 6 -0.5 0.5
region	        P3 block 22 25 3 4 -0.5 0.5
region	        P4 block 22 25 5 6 -0.5 0.5
region		P union 4 P1 P2 P3 P4

region	        S1 block 26 29 5 6 -0.5 0.5
region	        S2 block 26 27 3 6 -0.5 0.5
region	        S3 block 26 29 3 4 -0.5 0.5
region	        S4 block 28 29 1 4 -0.5 0.5
region	        S5 block 26 29 1 2 -0.5 0.5
region		S union 5 S1 S2 S3 S4 S5

region          LAMMPS union 6 L A 1M 2M P S
set		region LAMMPS type 2


mass		* 1.0 # 粒子の設定.

# 粒子-粒子間相互作用ポテンシャル
pair_style	lj/cut 2.5
pair_coeff	* * 1.0 1.0 2.5

timestep        0.005 # MDシミュレーションのtimestep.

# 高速化コマンド. neighbor list に入れる距離指定.
neighbor	0.3 bin
neigh_modify	delay 0 every 1 check yes

velocity	all create 2.0 87287 loop geom # 全原子の速度を初期化.


thermo		100 # 熱力学情報の出力頻度を設定
dump		1 all atom 20 output.lammpstrj # 20タイムステップごとに原子位置をoutput.lammpstrjというファイルにダンプ

# 100ステップのシミュレーションを積分せずに実行して"一時停止"させる
run		100

fix		1 all nve # 原子1についてNVEアンサンブルでシミュレーション.
fix		2 all enforce2d # 原子2のz次元の速度と力をゼロ.
run		1000 # 実行

# 設定を解除してシミュレーションを実行, 可視化を一時停止する.
unfix		1
unfix		2
run		200 # 実行

# 原子の速度を反転させ, シミュレーションを継続する.
variable        vxflip atom -vx
variable        vyflip atom -vy
velocity	all set v_vxflip v_vyflip NULL

fix		1 all nve # 原子1についてNVEアンサンブルでシミュレーション.
fix		2 all enforce2d # 原子2のz次元の速度と力をゼロ.
run		1000 # 実行

# 再び設定を解除してシミュレーションを実行, 可視化を一時停止する.
unfix		1
unfix		2
run		100 # 実行
```

## 快適にするために

私はjuliaを用いてある程度の自動化を行なっている. 具体的には以下のことをプログラムに任せている.

- いちいち打ち込む必要のあった`mpirun -n 4 -in in.input`を代わりに打ち込んでもらう.
- 出力されるファイルの接頭に実験時刻をつけて, ファイル名の一意性を守る.
- 出力されるファイルを拡張子ごとに分けて, outputdirというディレクトリに保存.

私のコードを参考にしたい方は以下を参照すると良い.

```julia
#=
lammpsファイルの実行及び出力ファイルの保管.
- lammpsファイル実行時に出力される*.logファイル,*.yamlファイルが指定した同一フォルダに,それぞれのフォルダを作成して保管される.
- lammpsファイルと同一ディレクトリにあるoutputファイルは削除.
- outputdirまでの絶対パスを任意に変更して使用してください.
=#

using Glob # *を使ってパターンマッチングするためのライブラリ.
using Dates # 日時を取得するためのライブラリ.

# lammpsfile=glob("in.*")[1] # 実行ファイルを指定.
lammpsfile="in.melt" # 実行ファイルを指定.
file_extensions = ["log", "yaml", "lammpstrj"] # 扱う出力ファイルの種類を指定.
outputpath = "/Users/2023_2gou/Desktop/r_yamamoto/Research/outputdir" # outputdirまでの絶対パス.

n = string(now())   # 実験日時の記録
remark = "logo"
run(`mpirun -n 4 lmp_mpi -log output.log -in $(lammpsfile)`) # lammpsの実行.

# 出力ファイルの保管.
for file_ext in file_extensions

    # 読み込みに失敗したら次のループに進む.
    try
        readfile = glob("*.$(file_ext)")[1] # 読み込みファイルを指定.
        script = read(readfile, String) # 読み込みファイルを読み込む.
        writepath = joinpath(outputpath, "$(file_ext)dir", "$(n)_$(remark)_$(readfile)") # 書き込みファイルの絶対パス.
        fp = open(writepath, "w") # 書き込みファイルを作成して開く.

        if file_ext == "log" 
            # logファイルのときに行う処理を記述.
            println(fp, "実験日時: $(n)") # 実験日時の書き込み.
        end

        write(fp, script) # 読み込んだテキストを書き込む.
        close(fp) # 書き込みファイルを閉じる.

        if file_ext == "yaml" 
            # yamlファイルのときに行う処理を記述.

        end

        if file_ext == "lammpstrj" 
            # lammpstrjファイルのときに行う処理を記述.

        end

        rm(readfile)

    catch
        
    end
end

```

## 参考になるもの

- [LAMMPS Documentation](https://docs.lammps.org/Manual.html)
  - ある程度慣れてから, 何かわからないところがあれば, とりあえずドキュメントを見ると良い.