Org-babelとFortran

Emacsに関する話. **Fortran** advent calendar 23日目

Fortran(やその他)のコードを**素早く**試したい方向け.
ソースコードはこれの`org-babel_and_Fortran.org`.
https://github.com/osada-yum/examples

- 実行環境
 - Emacs26.3 on Ubuntu20.04 on VirtualBox 6.1.14
 - Emacs28.0.50 on Ubuntu20.04
 - Org mode version 9.1.9

# [Org mode](https://orgmode.org/)
Emacsの文書作成モード, 他のエディタでも使える. MarkdownみたいにhtmlやLaTeXファイルを生成することもできる. Emacs26.3ではインストールなしで使える?

## [Org babel](https://orgmode.org/worg/org-contrib/babel/)
Org modeでコードを実行できるやつ. Emacs26.3ではインストールなしで使える? `org-babel-do-load-languages`で読み込む言語を指定. この記事ではこれらを使う. `org-src-lang-modes`はeditのときのモードを指定できる.
[対応言語](https://orgmode.org/worg/org-contrib/babel/languages/index.html), `M-x package-list-package`で`ob-*`を探せばもっとある. (`ob-prolog`とか`ob-rust`とか`ob-ess-julia`とか.)

```emacs-lisp
#+BEGIN_src emacs-lisp
(org-babel-do-load-languages
  'org-babel-load-languages
  '((emacs-lisp . t)
    (fortran    . t)
    (R          . t)))
#+END_src
```

### コードの実行
参考

https://orgmode.org/worg/org-contrib/babel/intro.html

http://misohena.jp/blog/2017-10-26-how-to-use-code-block-of-emacs-org-mode.html

### Fortranコードブロックの実行
`:exports`はhtmlやLaTeXへの変換に使用される. `:results output`は`#+RESULT`が標準出力の内容になる. `:cache yes`ならコードブロックの実行のキャッシュが取られて同じコードブロックの実行をする必要がなくなる.

![fortran_code1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2296800/178a8be6-e18b-2a84-6866-33798c9da2d5.png)
`#+BEGIN_src (language)`と`#+END_src`で囲む. (大文字でも小文字でも`#+BeGin_sRc`でもよい.)

![fortran_code_exec1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2296800/04f2b34f-8b06-0a10-285c-367dd18e80ed.png)
`C-c C-c`を押して`yes`で実行.

![fortran_code_edit1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2296800/1f0341fa-8c9e-65a3-563f-9e793b1b51fd.png)
`C-c C-'`で別のウィンドウ(Emacs用語)で編集できる. `C-c C-'`で終了. `C-c C-k`で取り消し.

![fortran_code2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2296800/2beb3ffc-74b9-3339-a1ca-fc804188e892.png)
単精度実数と倍精度実数は7桁程度一致していること. `acos(-1)`でも`4*atan(1)でも15桁程度一致している.

### コンパイラの変更
Emacsの変数の`org-babel-fortran-compiler`によって決まる. デフォルトでは`"gfortran"`. org-version 9.1.9では`defvar`で宣言されているので`setq`を使って変更する. (9.5では`defcustom`で宣言されているため, `M-x customize`で設定できる.)

```emacs-lisp
(setq org-babel-fortran-compiler "ifort")
```


### `f90-mode`でコードブロックの編集をする.
`#+BEGIN_src fortran`では`C-C C-'`を押したときのモードが`fortran-mode`となっている. `f90-mode`にするには`org-src-lang-modes`を変更すればよい.

```emacs-lisp
#+BEGIN_src emacs-lisp
(add-to-list 'org-src-lang-modes '("fortran" . f90))
#+END_src
```

### コンパイラのフラグの指定
拡張子が大文字の`.F90`なのでプリプロセッサが働くから`-cpp`はあってもなくてもよい.
結果のファイルを覗くと, コードブロック内の内容に`program main * end program`を付けていることが分かる. ファイル名はランダムで決まる. FOOはコンパイラによって置き換えられる. BARは暗黙の型宣言によって単精度浮動小数の未初期化の変数となっている.

```fortran
#+NAME: flag
#+BEGIN_src fortran :flags '("-cpp" "-DFOO=3") :results output table
  print*, __FILE__, __LINE__
  print*, FOO, BAR
#+END_src

#+RESULTS: flag
| /tmp/babel-eIDpbc/fortran-src-<random>.F90 |                        4 |
|                                          3 | <uninitialized-variable> |
```

### 表の出力の長さの制限を変える
`org-table-convert-region-max-lines`を変更する. ただ, `M-x describe-variable org-table-convert-region-max-lines`には大きいと`org-table-convert-region`が遅くなると書いてあるのであまり大きくしてはいけない.

```emacs-lisp
(customize-set-variable 'org-table-convert-region-max-lines 10000)
```

### Fortranでデータを生成してRでプロットしてみる.
`:var`の後に変数を指定できる. 変数には表も指定できる. fortranのコードブロックで`gen_rand`という名前の表を生成して, Rのコードブロックで`gen_rand`の結果を`vals`に代入して, プロットしている.

```fortran
#+NAME: gen_rand
#+BEGIN_src fortran :var n=1000 :exports results :results output table :cache no
  real(8) :: rnd(n)
  call random_number(rnd)
  print'(i0, a, es20.8)', (i, " ", rnd(i), i = 1, n)
#+END_src
```

```R
#+NAME: plot_ran_num
#+BEGIN_src R :var vals=gen_rand :exports results :results output graphics :file rand_num_plot.png :cache yes
  colnames(vals)[1:2] <- c("iterate", "random")
  plot(vals$random)
#+END_src
```

![fortran_R_plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2296800/18b267f1-b89b-2381-2a55-f92f9fc57a6d.png)

# まとめ
- Org babelでコードブロックを**素早く**実行できる.
- fortranをコードブロックで使うため, `org-babel-do-load-languages`を使用した.
- `f90-mode`をコードブロックの編集で使うため, `org-src-lang-modes`を変更した.
- あるコードブロックの結果を別のコードブロックから利用して図を描くことができる. 

# 結論
~~これはFortranの記事なのだろうか?~~
まあ, 例えば, [Intrinsic Procedures](https://gcc.gnu.org/onlinedocs/gfortran/Intrinsic-Procedures.html#Intrinsic-Procedures)を見て, `adjustl`と`adjustr`と`trim`の違いは何か調べたくなっても, 以下のようにして`C-C C-C`で素早く実行できるのはインタプリタではない`gfortran`にとってはプラスであろう.
(`lfortran`を使うという手もある上, `gfortran prog.f90 && ./a.out`で直ぐに実行できるけれども, 文字変更して直ぐに`C-c C-c`を押す方が速いはず.)

```fortran
#+BEGIN_src fortran :exports results :results output
  character(len=20) :: str = " gfortran "
  print'(2a)', "adjustl: ", "|"//adjustl(str)                   //"|"
  print'(2a)', "adjustr: ", "|"//adjustr(str)                   //"|"
  print'(2a)', "trim   : ", "|"//trim(str)                      //"|"
  print'(2a)', "|       |", "|"//"                             "//"|"
#+END_src

#+RESULTS:
: adjustl: |gfortran            |
: adjustr: |            gfortran|
: trim   : | gfortran|
: |       ||                             |
```

# 参考資料

## Org mode

https://orgmode.org/

### Org babel

https://orgmode.org/worg/org-contrib/babel/

https://orgmode.org/worg/org-contrib/babel/intro.html

https://orgmode.org/worg/org-contrib/babel/languages/index.html

http://misohena.jp/blog/2017-10-26-how-to-use-code-block-of-emacs-org-mode.html

## GFortran

https://gcc.gnu.org/onlinedocs/gfortran/Intrinsic-Procedures.html#Intrinsic-Procedures