モダンFortran勉強会.f02で出た話題

# 概要
モダンFortran勉強会.f02で出た話題のうち，プログラミング言語のテクニックや仕様に関わる話題まとめました．
ご意見頂ければ修正・加筆していきます．

# 更新履歴
- 2019年7月3日　@sakamoti さんの編集リクエストにより，微分方程式の数値解法の記述が充実しました．

# 困りごと相談/情報交換
## IMSLの代替があるか？
古いFortranコンパイラを使っていて，Runge-Kutta法と連立一次方程式のソルバーにIMSLライブラリを使っている．Intel Fortran+IMSLライブラリだが，販売が終息している．業務としても，今後のことを考えれば，できればgfortranに置き換えたい．
何かないか？

### 挙げられた候補
- いわゆる数値計算ライブラリ
    - [NAGの数値計算ライブラリ](https://www.nag-j.co.jp/naglib/fl/index.htm)（有償）
    - MKLは？
    - [GSL](https://www.gnu.org/software/gsl/)は？（GPLライセンス）　C言語用だが、fortranバインディング([fgsl](https://doku.lrz.de/display/PUBLIC/FGSL+-+A+Fortran+interface+to+the+GNU+Scientific+Library))を開発している人がいる。
- 微分方程式の数値解法（Runge-Kutta法の代替となるもの）
    - 一段解法(Runge-Kutta法)
        - [RKSUITE](http://www.netlib.org/ode/rksuite/)　Fortran90/77版，C++版がある．
          IMSL(IVMRKルーチン)やNAG(D02PVF,D02PYF,D02PZFルーチン)に取り込まれて発展
     した経緯がある。

    - 線形多段解法(Adams法,BDF法)
        - [ODEPACK](http://www.netlib.org/odepack/opkd-sum)
          　LSODE, LSODA など、複数のソルバが含まれている。GNU Octaveではlsode関数がこれを呼び出している。ScipyではODEソルバの一つとしてlsodaを選ぶことができるが、fortran版の全ての機能を利用できるわけではない。
        - VODE/CVODE　LSODEより後に開発が開始．ローレンスリバモア研究所の[SUNDIALS](https://computation.llnl.gov/projects/sundials)に含まれている．
    [このページ](http://lh3lh3.users.sourceforge.net/solveode.shtml)によると，

        > LSODE and VODE are probably the best known ODE solvers

        とのこと．

    - [SUNDIALS](https://computation.llnl.gov/projects/sundials)　ルンゲクッタ法や線形多段解法(VODE)を含む微分方程式の解法群。      開発時期は比較的新しい。C言語で開発されているが、fortranインターフェイスも有している。

- 連立一次方程式
    - [Lapack](http://www.netlib.org/lapack/)

### 古いIntel Fortran (2011)から新しいgfortranへの移行に際しての，リスクやメリット/デメリット
- 古いIntel Fortranを使い続けるのはデメリットしかない．
- 2011だと，Visual Studioのバージョンは2005のはず．VSも数年前のアップデートで大幅に変わっているので，今後の事を考えると移行する方がよい．
- Windows 7のサポートが切れて，Windows 10へ移行する時に困る．
- Intel Fortranの独自拡張に慣れていると，gfortranへ乗り換えるときに，最初かなり修正が必要になることがある．（[参考](https://qiita.com/implicit_none/items/574cbb9440c851422efe#デバッグ方法について)）

## コードが読める状態から，新しいルーチンを書けるように育てるには？
新人がFortranコードを読めるようになった．その後，自前で新しいルーチンを作れるようにするには，どのようにすればよいか？
どうやってコード実装のロジックを考えているのか？

- フローチャートを書くとか．
- 一般的に難しい問題．
    - プログラミング言語の文法を習った後，ロジックを考えて処理に落とし込めるようになるには高いハードルがある．
    - プログラムを書けることと，ロジックを考えられることは別．
    - 書籍がほとんど無くて，秘伝のFORTRANソースしかない状態ではさらにハードルが高い．
- 小さい問題で慣れさせて，徐々に大きな問題に取り組ませるのがよいのでは．
- 本は何か買ったの？
    - 定番の2冊を買った
        - [数値計算のためのFortran90/95プログラミング入門](https://www.amazon.co.jp/数値計算のためのFortran90-95プログラミング入門-牛島-省/dp/4627847211/)
        - [Fortran90/95プログラミング](https://www.amazon.co.jp/Fortran90-95プログラミング-冨田-博之/dp/4563015873/)
    - 私のお勧めは[入門Fortran90](https://www.amazon.co.jp/入門Fortran90-ラリー-ニーホフ/dp/4894713217/)．

# 話題提供
## モダンFortranのコーディングルール
モダンFortran用のコーディングルールがない．"Fortran コーディングルール"で検索すると，[気象庁](http://www.mri-jma.go.jp/Project/mrinpd/coderule.html)か[北大](https://www.ep.sci.hokudai.ac.jp/~mosir/work/2001/0822/muroi/src/siryou/coderu~1.htm)のページがヒットする．
困っていなかったが，モダンFortran勉強会.f01で「少し古いよね」という意見があった．確かに2005年から更新されていない．
海外では，○○（プロジェクト）のためのコーディングルールという定め方になっていて，統一的なルールがない．

- 最新のFortranにも対応できるコーディングルールはあった方がよい．
    - やった方がいい事，やってはいけない事，できるけどやらない方がいい事をまとめるのは必要．
        - できるけどやらない方がいい事の代表は，ポインタの利用．
            - ポインタを使ってallocateした後deallocateせずにメモリリークしている場面が多くある．
    - Fortranの書き方だけでなく，プログラムの設計にまで踏み込んで解説が必要になることがある．
    - 命名規則
        - 大文字小文字の区別がないFortranでは，Fortran独自のやり方が必要．
        - アンダーラインで区切ろうにも，変数名に31文字制限のあるFortranでは，その制限に引っかかりやすくなる．
    - Githubにリポジトリをたてて，Issueで議論しましょう．

## Assumed-size arrayとAssumed-shape array
関数/サブルーチンに配列を渡す時，Assumed-size arrayあるいはAssumed-shape arrayがある．どっちを使うのがよいか？

- 人間にとって親和性があるのはAssumed-shape arrayだからそっちを使うべきでは？
    - 実行速度を比べると，Assumed-size arrayの方が明らかに速い．
    - Assumed-size arrayは，配列のサイズと先頭アドレスだけあればよいので，多次元配列でも1次元配列のように処理することで最適化が効いている？
- Assumed-sizeの方が速いから親和性のある方を使わない，というのはダメだろう．代理店なりを通してコンパイラベンダーに情報を上げ，Assumed-shape arrayでも最適化されるようにした方がよい．
    - 文句言うだけで終わり，は何も生まないからもう止めよう．
    - ロボ太御大の[お言葉](https://twitter.com/kaityo256/status/1144492720540413952)．
- C言語との混合言語プログラミングで，C言語から配列を渡す時はAssumed-size arrayとして受けるので，Assumed-size arrayも適材適所で使えばよい．


## (主にC++と比較して)HPCでFortranを使うべきとき, そうではないとき
以前いた研究室ではみんなFortranを使っていたが，現在の研究室ではみんなC++を使っている．

- Fortranはアドレスが連続な配列に対する処理に強い．
- ビット演算などは，2003移行で対応できるが，速いか，使いやすいかは疑問．
- みんなC++を使っているのに一人だけFortranだと，進捗が出なかったときに，「Fortranなんか使ってるだろ」となる可能性がある．
- 研究室の方針に沿ってC++を覚えながら，Fortranに反映するのは？
- Fortranだけを長く使っていてもプログラミングが上手くなったりはしないが，他言語を使って，その言語で上手く書けるようになると，Fortranも上手く使えるようになる．

## RまたはPythonからモダンFortranライブラリを呼ぶ
Fortranで作ったクラスをRやPythonから呼びたいが，Fortran 90以降で追加された機能は渡せない．今はFORTRAN 77のルーチンを間に挟んで，それを呼んでいる．
ルーチンを作るにも手間がかかるので，なにかよい方法はないか？

- そのやり方がベスト．
- R言語がCとFORTRANで作られており，その影響でFORTRANを呼べるが，Fortran 90以降には未対応．
    - Rに限らず，どの言語でもそんな感じ．
    - PythonもC言語の関数は呼べるので，subroutine() bind(c)でCの関数に見せかけることで，Pythonから呼べるようにしている．
- 必要があれば，Fortran 90以降のクラスを呼べるようなモジュールやパッケージを作る事ができればよいのだが，Fortranユーザの専門スキル的になかなか手が出せない．
    - [Open Fortran Parser](https://github.com/OpenFortranProject/open-fortran-parser)がある．
    - 過去にFortran 90の[パーサ](https://github.com/nomaddo/f90)を実装しようとした方もいて，[苦労が伺える](http://no-maddojp.hatenablog.com/entry/2016/12/01/023624)．

## 開発環境やエディタのおすすめ
Fortranを書くときには，エディタは何がよいか？
LinuxやMacでFortranを書く人からよく尋ねられる．

- 勉強会参加者のアンケート

|エディタ|使用人数|
|:--|:--:|
|VSCode|4名|
|Atom|2名|
|Vim|8名|
|Emacs|2名|
|Visual Studio|2名|

- VSCodeは強い
    - WindowsでもLinuxでもMacでも同じように使い方を説明できる．
    - みんな同じようなインタフェースだが，自分だけ拡張を入れて使いやすくするとか．
    - Vim使っている人向けに，キーバインドを再現する拡張もある．
- VimだとCUDA Fortranのシンタックスハイライトにも対応してるよ．

（一般的には荒れそうな話題だが，荒れることなくみんな納得の結果に落ち着く．）

## FEMのプログラムについて
Fortran 90/95と銘打っている有限要素法の書籍を購入したのだが，全て大文字で書いてあるし，本に載っている式とプログラムが違うし，サブルーチン引数も配列にすればいいのに個別変数で渡している．

- 式とプログラムが違うのは，式通りだと非効率だから変えているのでは？
    - その他のプログラムリストをみるに，そこまで気を回したわけではなさそう．
- Fortranは引数の個数に制限がないので，サブルーチン引数は多くなりがち．
    - 配列で渡す場合と，個別の引数で大量に渡す場合で速度は変わる？
        - 結構変わる．プロファイルを取ってみると，まれに呼出しのタイミングでものすごく時間がかかっていることがある．
        - 引数の数が多いとどんどんスタックに積まれていく．
            - その辺のハードウェアに近いローレベルのことはどうやって勉強すればいいんですか？
                - PICマイコンとか．
                - Fortranだけを勉強してもハードウェアは詳しくならない．

## モダンFortranはC++に比べて，コンパイラ最適化がどれほど有利なのか
次世代スパコン「富岳」の重点課題で開発するアプリのうち，Fortranでないのは一つだけ．そんなにFortranがいいのか？何がいいのか？

- C/C++言語では仕様上，勝手にコンパイラ最適化できないような場合でも，Fortranでは最適化できるなど，あまり詳しくない人が書いても最適化してくれるのが強み．数値計算の用途に合っている．

# 発表
## EQUIVALENCE無しで実フーリエ変換を利用する
- モダンFortran勉強会.f01で`equivarence`の代替機能について尋ねた．
- 挙げられた候補のうち，Cのポインタを利用する方法を試した．
- [結果](https://qiita.com/yotakagi77/items/d2db19bf8d8cb64e8e46)
    - $256^3, 512^3,1024^3$の点数で`equivalence`版とCポインタ版の実行速度を調べた．
        - FLOPS値はCポインタの方が少し高い．
        - ADB(Assignable Data Buffer)のヒット率は`equivalence`の方が高い．
        - 差は微小で，Cポインタを利用することで，`equivanlence`を使わずスペクトル法を実装できそう．

## fortran-utilsの続編的なこと
- [資料](https://modern-fortran-local-user-group.connpass.com/event/132269/presentation/)
- [モダンFortran勉強会.f01で紹介](https://qiita.com/implicit_none/items/574cbb9440c851422efe#fortranをpythonに近づけろfortran-utilsを使ってみた)した[fortran-utils](https://github.com/certik/fortran-utils)のコードリーディング
- fortran-utilsにassert()が定義されている．
    - Fortranにも普通にassertが欲しい
    - プリプロセスが許される環境なら，`optional`引数で`__NAME__`や`__LINE__`も扱えるようになるので，自前で用意するのもよい．

## cmakeによるFortran90ビルドの省力化
- [資料](https://qiita.com/ijknabla/items/05270ae5e597705d0dae)
- モダンFortran勉強会.f01のときに，cmakeいいよと言ったので，その使い方をまとめた．
- Fortranだとmakeでコンパイルの順序を手作業で打つような場合も多いが，cmakeは依存関係を自動で解析してくれる．
- 並列コンパイルも可能．
- ロードするモジュールも確認できる．
    - Intel MPIとOpenMPIを併用していると，リンクできずにドツボにハマる場合もあるが，cmakeはパスも含めて出してくれるので間違えない．
- ctestも利用でき，ビルド時にテストができる．
- スパコンなんかだとインストールされているcmakeが古い（安定版で固定されている）ことが多々あるので，新しいcmakeを使いたい場合はcmakeでcmakeをビルドするとよい．

## Modern Fortran Explainedの読書報告(目次、1章)
- [Modern Fortran Explined（赤）](https://www.amazon.co.jp/dp/B07LGZKJ4X/)の輪読を一人で始めた．
    - 2018年版が赤
    - 2011年版が緑
- 1章ではFortranとは何か，Fortranの歴史が述べられており，意外に知らないことがあった．
    - 真にモダンといえるFortranは2003から．
    - 規格策定の遅れ期間が徐々に伸びてきている．
- 輪講に参加したい人は声をかけてください．

## いくつかのデザインパターンのFortran実装
- FortranでGoFのデザインパターンのいくつかを実装した．
    - Strategy パターン　普通に実装でき，とても重宝する．
    - Factory Methodパターン　普通に実装できる．
    - Iteratorパターン　Fortranのオブジェクト指向プログラミング機能の限界．実装はできるが再利用性がない．
    - Singletonパターン　使い道はないが，ポインタを使えば実装できる例．
- Fortranでは，クラス定義の方法が変
    - 他言語では，クラスの宣言の中にメソッドの実装を書く
    - Fortranでは，クラスの宣言の外にメソッドの実装を書く
        - 実質1モジュール1クラスに制限される．
    - 大文字小文字の区別がなく，命名が大変なのに，モジュール名，クラス（派生型）名，変数名を決めなければならない．