# 津波コードの使用方法
## 概要
研究室で受け継がれている津波コードですが,以下の課題があります.
- `implicit none`が行われていないこと
- `main`や`subroutine` が1つのファイルにまとめられておりこと
- 並列化されていないこと
- 接続領域を変更するたびに`main`コードを書き換える必要があること
研究で津波計算を行うたびに,これらの問題点で結構苦しめられたので,コードを書き直しました.
書き直す際にやったことは様々あるんですけど,説明すると長くなるのでやりません.
今回は新しくしたコードの使い方を示します.一応デバッグはしましたが,不具合が生じた場合はお知らせください.
## 目次
1. ファイル構成
2. パラメータ設定
3. コンパイル・実行
4. あとがき
## 1.ファイル構成
1つにまとめられていたコードを,以下のような複数ファイルに分けました.
|ファイル名|説明|
| ---| ---|
|MakeFile|コンパイルするときに必要なファイル|
|tnm_main.f90|mainコード,基本的に触らない|
|tnm_sub.f90|subroutineコード,基本的に触らない|
|tnm_input_file.f90|ファイル名設定コード,入出力ファイルの場所をここで指定する|
|tnm_input_vals.f90|パラメータ設定コード,計算に必要な変数の設定を行う|
基本的にはinputの2つだけをいじると計算が回るようになっています.
mainとsubコードは機能を増やす時に書き換える必要がありますが,勉強をしてからにしましょう.
## 2.パラメータ設定
2つのinputファイルの設定方法を記します.
- tnm_input_file.f90
コードの中身をさらっと見せると以下の通りです.(第一領域のみ)
```fortran=
module input_file
!
implicit none
!
character*64,parameter :: F_OP1 = 'outpoint/outpoint1.dat'
!
character*64,parameter :: F_DF1 = 'deform/deform1.dat'
!
character*64,parameter :: F_BT1 = 'bathymetry/region1.dat'
!
character*64,parameter :: F_POUT1 = 'result/point1.dat'
!
character*64,parameter :: F_ZMAX1 = 'result/max1.dat'
!
character*64,parameter :: F_VMAX1 = 'result/vmax1.dat'
!
character*64,parameter :: F_IND1 = 'result/inund1.dat'
!
character*64,parameter :: F_AT1 = 'result/atime1.dat'
!
end module input_file
```
各変数の説明は以下の通りです.(第1領域)
|変数|説明|status|
|---|---|---|
|F_OP|波形出力点|old|
|F_DF|初期水位(deformコードにより作成)|old|
|F_BT|地形データ|old|
|F_POUT|出力波形|unknown|
|F_ZMAX|最大水位分布|unknown|
|F_VMAX|最大流速分布|unknown|
|F_IND|最大浸水深分布|unknown|
|F_AT|到達時間分布|unknown|
文字数は見ての通り64文字に設定しているので,それ以内に抑えるようにしてください.
また不要なoutputがある場合でも(流速や浸水深),コメントアウトせずに使用してください.
- tnm_input_vals.f90
同じく,第一領域を見せると以下の通りです.(大分見づらいと思うので,
```fortran=
module input_vals
!
implicit none
!
integer,parameter :: K6 = 100, KP = 60
real,parameter :: FM = 0.025, GG = 9.8, SH = -50.0 ! --- SH = 0.0:MNTK, -50.0:NLMNT
!
integer,parameter :: KL = 3600
real,parameter :: DT = 0.1
!
! <-- Boundary Condition --->
! BC = 0.0 : vertical wall B.C.
! = -30.0 : uphill B.C.
real,parameter :: BC = -30.0
!
integer,parameter :: RN = 6
integer,parameter :: P_FORM = 0 !--- 0 : ASCII, 1 : BINARY(little endian) ---
integer,parameter :: FL_MNT = 0 !--- 0 : NLMNT, 1 : MNT , 2 : LNMNT
!
integer,parameter :: NRU(6) = (/0,0,0,0,1,1/) ! <--inund--- 0:NO, 1:yes ---
!
! - * - * - * - * - region1 - * - * - * - * -
integer,parameter :: IF1 = 691, JF1 = 1018
integer,parameter :: NP1 = 101
integer,parameter :: KSNZ1 = 100, KSTRT1 = 0, KEND1 = 54000
integer,parameter :: IZS1 = 1, IZE1 = 691, JZS1 = 1, JZE1 = 1018
real,parameter :: DX1 = 1215.0, DY1 = 1215.0
integer,parameter :: ISNV1 = 0, KSNV1 = 3000
integer,parameter :: IVS1 = 1, IVE1 = 691, JVS1 = 1, JVE1 = 1018
!
integer :: NC1
real,parameter :: RX1 = DT/DX1, RY1 = DT/DY1
character*40,dimension(NP1) :: PNAME1
real,dimension(IF1,JF1) :: HZ1, HM1, HN1, ZM1
real,dimension(IF1,JF1,2) :: Z1, M1, N1, DZ1, DM1, DN1
integer,dimension(NP1) :: IP1, JP1
real,dimension(IF1,JF1) :: VM1, ZI1
real,dimension(IF1,JF1,2) :: VEL1
real,dimension(IF1,JF1) :: AT1
integer,parameter :: I_PT1 = NP1+1, J_PT1 = KL/KP
real,dimension(I_PT1,J_PT1) :: WP1
!
end module input_vals
```
各変数の説明は,変更するもののみ行います.
|行数|変数|説明|
|---|---|---|
|5|KP|波形出力間隔,波形出力点の時間間隔のステップ数<br>(上例だと`DT=0.1`の`KP=60`なので,6秒間隔)|
|6|SH|モーメントの計算上限水深,<br>`FL_MNT=0`のとき`SH=-50.0`, `FL_MNT=1 or 2`の時,`SH=0.0`
|8|KL|再現時間のステップ数(上例では,360秒)
|9|DT|計算時間間隔,ある程度の細かさが必要
|14|BC|境界条件,遡上境界の場合`-30.0`,<br>完全反射境界の場合`0.0`(`FL_MNT=1 or 2`の場合も)
|16|RN|計算領域数,`1~6`で指定,ここを間違えると計算が回らない可能性大|
|17|P_FORM|出力形式(波形出力データのみ,snapについては今後追加予定)|
|18|FL_MNT|支配方程式の指定,<br>非線形長波:`0`,線形長波(摩擦あり):`1`,線形長波(摩擦なし):`2`|
|20|NRU|浸水深の出力指定,各領域毎に指定|
|23|IF,JF|領域の格子数(x,y)|
|24|NP|波形出力点数|
|25|KSNZ|水位スナップの出力間隔ステップ数|
|25|KSTRT<br>KEND|スナップの出力開始,終了ステップ数|
|26|I(J)ZS<br>I(J)ZE|水位スナップの出力範囲,<br>無駄を減らすときは範囲を絞ると楽になる|
|27|DX,DY|格子サイズ(m)|
|28|ISNV|流速出力指定,`0`:出力なし,`1`:出力あり|
|28|KSNV|流速出力間隔ステップ数,基本的にはKSNZと同じくする|
|29|I(J)VS<br>I(J)VE|流速スナップの出力範囲,<br>I(J)ZS,I(J)ZEと同じくする|
これらを計算する領域分指定するだけです.簡単ですね.
計算は第6領域までしかしない想定で作成したので,それ以上の計算が必要な場合は(そんな計算しないと思いますが),書き換える必要がありますので気をつけてください.
## 3.コンパイル・実行
- コンパイル
1で示したファイルを1つのディレクトリにまとめてください.
私は`module`というディレクトリにまとめています.
パラメータの設定が終わったら,以下を実行します.
```
$ make
```
問題がなければ以下のファイルが生成されます.
- tunami
- input_file.mod
- input_vals.mod
- routines.mod
このうち,実行ファイルはtunamiです.
これを実行する場所に移動して,実行します.
- 実行
実行ファイルtunamiを実行する場所に移動しましょう.
実行する場所とは,地形データや初期水位データがある場所です.
例としては,以下のような配置を示します.
- bathymetry
- region1~6.dat
- outpoint
- outpoint1~6.dat
- deform
- deform1~6.dat
- result
- elr
- vxr
- vyr
- tunami
- run_tunami.sh
- module
同じ場所でコンパイルしてもいいですが,ファイルが多くなりすぎて困るので,別のディレクトリにしましょう.
実行ですが,普通に以下のように行ってもできます.
```
$ ./tunami
```
しかし,せっかくなのでshellファイルを使用して実行しましょう.
shellファイル`run_tunami.sh`は以下のようになります.
```sh=
#usr/bin/bash
ulimit -s unlimited
./a.out
```
これを以下のように実行します.
```
$ sh run_tunami.sh
<バックグラウンドの場合>
$ nohup sh run_tunami.sh -&
```
これでファイルの指定がちゃんとできていれば,計算できます.
<発展>
上で示したshellファイルは単純すぎるため,shellを使う意味があまりありません.(shellの使い方の練習にはいいかも)
なので,コンパイル・実行ファイル移動・実行 を一気にやりましょう.
`run_tsunami.sh`を以下のように書き換えます.
```sh=
#usr/bin/bash
rm tunami
cd module
make
mv tunami ../
cd ../
ulimit -s unlimited
./tunami
```
これを以下のように回せば,割とスマートにできると思います.
```
$ nohup sh run_tunami.sh -&
```
## 4.あとがき
この記事では,簡便化したtunamiコードの使い方を示しました.
基本的には,この通りに回せば簡単に回るかと思います.
このコードを作成するにあたり,作るべきか少し迷いました.
理由は,簡単になりすぎると,構造などを理解せずとも計算ができてしまうからです.
しかし,tunamiコードはとても長いコードであり,理解するにはとても長い時間を要します.
人によって差はあると思いますが,私はM1のときに1ヶ月以上,それだけをやることで多少理解できました.
まあ,何が言いたいかというと,できれば理解を深めてから使用してほしいですが,時間的な制約があると思うのでこのコードを有効に活用して欲しいということです.(できれば感謝しながら 笑 )
計算モデルの研究を主に行う人の場合は,是非main,subコードを読んでください.
そして,不適切な部分や改良の余地がある場合は,どんどん書き換えていってください.
断層の破壊時間を考慮したコードやsnapのバイナリ出力コードは,時間があれば追加していきたいと思います.
これらが急ぎで必要な場合は連絡ください.努力します笑.
###### tags: `tunami`, `Fortran`