1
Help us understand the problem. What are the problem?

posted at

updated at

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

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

Org babel

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

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

コードの実行

参考

Fortranコードブロックの実行

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

fortran_code1.png
#+BEGIN_src (language)#+END_srcで囲む. (大文字でも小文字でも#+BeGin_sRcでもよい.)

fortran_code_exec1.png
C-c C-cを押してyesで実行.

fortran_code_edit1.png
C-c C-'で別のウィンドウ(Emacs用語)で編集できる. C-c C-'で終了. C-c C-kで取り消し.

fortran_code2.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で設定できる.)

(setq org-babel-fortran-compiler "ifort")

f90-modeでコードブロックの編集をする.

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

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

コンパイラのフラグの指定

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

#+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が遅くなると書いてあるのであまり大きくしてはいけない.

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

Fortranでデータを生成してRでプロットしてみる.

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

#+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
#+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

まとめ

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

結論

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

#+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

Org babel

GFortran

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
1
Help us understand the problem. What are the problem?