SWATソースコードのコンパイル方法

## SWATのソースコードについて

- SWAT2012のソースコードはFortranを使用して記述されている。
- Fortranの中でもかなり形式の古い（1990年より前に主流だった）.fファイル（固定形式）で構成されている。
- 最近のバージョンで追加されたファイルは.f90ファイル（自由形式）で書かれている。
- .fファイルと.f90ファイルが混在している。

## 注意点

- この方法はVisual StudioとIntel one APIを使用して作成した.exeファイルがなぜかSWATrunRで動作しなかったため、考案された方法。
- Fortranに関する勉強をほとんどしないまま、コンパイルのみ可能にしたため、もっと良い方法があるはず。
- Visual Studioで作成した.exeファイルがそのまま使えるならそのまま使った方が良いと思う。
- 既にPCにインストールされているものを再びインストールする必要なし。

## Fortranについて

- 一般的に全世界で使用された世界最古のプログラミング言語。
- 現在では、非常に軽く動作するという特徴を使用して、数値計算の分野で主に使用されている。
- プログラムの記述形式は「固定形式」と「自由形式」の2種類が存在する。

|  | 固定形式 | 自由形式 |
| --- | --- | --- |
| 拡張子 | .f | .f90 |
| 文字数制限 | 1行に72文字まで | 1行に132文字まで |
| 行始め | 全ての行で6文字分スペースを入れてから記述開始 | 特に制限ナシ |
| 継続行 | 左から6文字目に&を入れて継続行を記述 | 継続行の一つ上の行の最後に&を入れる |
- 1990年以降はほとんど.f90ファイルで記述されているのに、なぜかSWAT2012では.fファイルが主に使われている。
- 作成したコードをコンパイルして実行ファイル（.exeファイル）を作成して、コードを動かす。
- 1つのメインコード、1つのモジュール、複数のサブルーティンで構成されていることが多い。
    - 構成ファイル同士で変数や関数を共有しており、依存関係がはっきりしている。
- 複数の.fファイルから一つの.exeファイルをコンパイルする際には、コンパイルする順番が非常に大切になる。

## Cmakeについて

- Fortranの複数ファイルのコンパイルではその順番が非常に重要。
    - しかし、SWATのソースコードのような大量のファイルをコンパイルする際に手動で依存関係を入力することは難しい。
    - この順番を指定するためにMakefileを作成する。
- CMakeは開発環境に合わせて順番を指定するファイルを作成してくれるツールで、コンパイル順も読み取ってくれる。

## コンパイルの流れ

1. どこかからSWAT2012のソースコードを入手する。
2. （Visual StudioとIntel one APIとCMakeをインストール。）
3. Visual Studioを使用してデバック。
4. CMakeLists.txtファイルを作成。
5. Intel one APIのコマンドプロンプトからifxを使用してコンパイル。

## 使用するツール（使用したバージョン）

- Microsoft Visual Studio Community 2022 64ビット（Version 17.10.3）
- Intel one API HPC Toolkit （Intel Fortran Compiler Version 2024.2.0）
- Intel one API Base Toolkit（Version 2024.2.0）
- CMake（Version 3.29.6）

## SWAT2012のソースコードを入手

- 基本的には[SWAT公式HP](https://swat.tamu.edu/software/swat-executables/)からBitbucketに飛んでダウンロード。
    - ただし公式から直接入手したソースコードはエラーまみれなのでデバックが必要。
- 公式のソースコードの修正をしてくれている神様↓

https://github.com/crazyzlj/SWAT  

- このGitHubのsrcファイルの中に修正済みのSWAT2012_rev692のソースコードが入っている。

## Visual Stusioのセットアップ

詳しくは[こちらの記事](https://qiita.com/Kazutake/items/a069f86d21ca43b6c153)を参照。

### １. Visual Studioのインストール
- 下記サイトからVisual Studioのインストーラーを入手。

https://visualstudio.microsoft.com/ja/
    
- Qiita記事には2022は良くない的なこと書かれているが、2022でも問題なし。
- インストール中、「ワークロード」のところで、「デスクトップとモバイル＞C++によるデスクトップ開発」 にチェックを入れてインストール。
   
### ２. Intel one API Base Toolkitのインストール
- 下記サイトの「Download the Toolkit」の下にある「GetItNow」から「windows」と「Online Installer」を選択。
    
https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit.html
    
- メールアドレスとお住まいの地域を入力して「Submit & Begin Download」をクリック。
- インストール

### ３. Intel one API HPC Toolkitのインストール
- 下記サイトから「windows」と「Online Installer」を選択して、メールアドレスとお住まいの地域を入力して「Submit & Begin Download」をクリック。
    
https://www.intel.com/content/www/us/en/developer/tools/oneapi/hpc-toolkit-download.html
    
- インストール

### ４. ソースコードをデバック 

- Visual Studioを起動して、新しいプロジェクトを作成の部分で「Empty Project; Fortran, Windows, コンソール」を選択。
- 適当なファイル名とフォルダを選択。
- ソリューションエクスプローラーからソースファイルを右クリックし「追加→既存の項目」を選択。
- SWAT2012のソースコードを全て選択して追加。
- メニューバーの下あたりで「Debag、x64」を「Release、x64」に変更
- メニューバーから「ビルド→ソリューションのビルド」を選択。
- ビルドが成功したらソースコードに問題なし、失敗したらソースコードに問題があるためデバックが必要。
    - 公式からダウンロードしたからと言って、正常に動作するとは限らない。
- 作成したフォルダ内でx64フォルダが存在する場所にTxtInOutの中身を全てコピペ。
- メニューバーから「デバック→デバックなしで開始」を選択。
- ArcSWATで実行したときと同様の画面で実行できるはず。
    - 作成したoutput.stdなどの値が正常かを必ず確認。
    - 正常でなければ、他の方法でコンパイルしてエラーを確認する必要がある。
- **GitHubの修正済みソースコードを使えばデバック必要なし！**

## コンパイルしよう

- [こちらのQiita記事](https://qiita.com/implicit_none/items/1e9314426edfd34d92f8)と[こちらのGitHub記事](https://github.com/crazyzlj/SWAT)の記事を大いに参考にした。
- ただし、Qiitaの元記事はGCC on Linuxを使用しているが、今回はMSVC on Windowsを使用。

### １. CMakeのダウンロード
- 下記サイトからPlatformが「Windows x64 Installer:」になっている適当なインストーラーを入手。
    
https://cmake.org/download/
    
- インストールオプションでは「Add CMake to the system PATH for all users」を選択。

### ２. Intel one API HPC ToolkitとCMakeを環境変数に設定（記述中のPCはwindows10）

- 「設定→システム→詳細情報→システムの詳細設定→環境変数」を選択。
- 下の「システム環境変数(S)」の「Path」行を選択し編集をクリック。
- ここにIntel one API HPC ToolkitのFortranコンパイラーとCMakeの実行ファイル（.exeファイル）の存在する場所を新規で入力する。
    - デフォルト設定で入れるとIntel one API HPC Toolkitは「C:\Program Files (x86)\Intel\oneAPI\compiler\2024.2\bin」。
    - デフォルト設定で入れるとCMakeは「C:\Program Files\CMake\bin」。
    - 既に存在している場合は新しく入れる必要なし。
- OK連打。
- コマンドプロンプトを開いて「ifx」または「cmake」と入力して「内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして認識されていません。」と表示されなければ成功。

### ３. コンパイルの順番を決めるファイル作成
- ソースコードの入ったフォルダを任意の場所に作成。
- 下記のようなテキストファイルを作成。
    
    ```pcp:CMakeLists.txt
    ## CMakeのバージョンを宣言
    cmake_minimum_required(VERSION 3.29.6)
    
    ## Fortranを使う際に必要な設定
    enable_language(Fortran)
    
    ## プロジェクト名(hello)と使用言語(Fortran)を宣言
    project(hello Fortran)
    
    ## フォルダ内の拡張子.fと.f90のファイルをそれぞれ入手
    file(GLOB F77SRCS *.f)
    file(GLOB F90SRCS *.f90)
    
    ## SWAT2012のソースコードの.fファイルは3種類の形式で記述されている
    ## それぞれの記述形式のpropertyを変数に格納
    set(FLAG_L72 /4L72)
    set(FLAG_L80 /4L80)
    set(FLAG_LLONG /4L132)
    
    ## 固定長72の特殊形式のファイル
    set(LEN72_SRCS "grow" "tran")
    ## 固定長132の長さを持つが、.f拡張子を持つ特殊形式のファイル
    set(LENLONG_SRCS "subbasin")
    ## .fファイルのpropertyを設定する
    foreach(F77FILE ${F77SRCS})
        get_filename_component(CORENAME ${F77FILE} NAME_WE)
        list(FIND LEN72_SRCS ${CORENAME} _FOUND_LEN72)
        list(FIND LENLONG_SRCS ${CORENAME} _FOUND_LENLONG)
        if(${_FOUND_LEN72} GREATER -1)
            set_source_files_properties(${F77FILE} PROPERTIES COMPILE_FLAGS ${FLAG_L72})
        elseif(${_FOUND_LENLONG} GREATER -1)
            set_source_files_properties(${F77FILE} PROPERTIES COMPILE_FLAGS ${FLAG_LLONG})
        else()
            set_source_files_properties(${F77FILE} PROPERTIES COMPILE_FLAGS ${FLAG_L80})
        endif()
    endforeach()
    
    ## .f90ファイルのpropertyを設定
    foreach(F90FILE ${F90SRCS})
        set_source_files_properties(${F90FILE} PROPERTIES COMPILE_FLAGS ${FLAG_LLONG})
    endforeach()
    
    ## 実行ファイル名(${PROJECT_NAME})と入力ファイル(${F77SRCS}, ${F90SRCS})を指定
    add_executable(${PROJECT_NAME} ${F77SRCS} ${F90SRCS})
    
    ```
    
- 名前を「CMakeLists.txt」とし、ソースコードと同じフォルダ内に入れる。


### ４. いざコンパイル

- Intel one APIの「command prompt for Intel 64 for Visual Studio 2022」を起動。
- ディレクトリをソースコードが含まれるフォルダに移動。
- フォルダ内に「build」フォルダを作成し、そこに移動。
- 「cmake .. -T "fortran=ifx"」コマンドを入力。
- 「cmake --build . --config Release」コマンドを入力すると、コンパイルしてくれる。
    
    ```pcp:command prompt for Intel 64 for Visual Studio 2022
    C:\Program Files (x86)\Intel\oneAPI> cd (ソースコードの入ったディレクトリ)
    (ソースコードの入ったディレクトリ)> mkdir build
    (ソースコードの入ったディレクトリ)> cd build
    (ソースコードの入ったディレクトリ)\build> cmake .. -T "fortran=ifx"
    (中略)…
    (ソースコードの入ったディレクトリ)\build> cmake --build . --config Release
    (中略)…
    ```
    
- コンパイルされた実行ファイル（.exeファイル）はbuildフォルダ→x64フォルダ→Releaseフォルダにある。
- 適当なTxtInOut内にコピペして実行できるか確認。
- output.stdなども確認

## まとめ
良いSWATコンパイル生活を！