LoginSignup
15

More than 3 years have passed since last update.

格子計算プログラム生成言語Formuraを使ってみる その1

Last updated at Posted at 2019-06-12

はじめに

プログラマは計算機に対して、「別に凝ったをやれとは言わないが、自明なことはやってくれよ」と思うものだ。例えば規則格子における差分法、特に陽解法は、式と差分方式さえ決まれば、(最適化とか考えなければ)後は自明なコーディングになる。さらに、領域分割による分散メモリ並列を考えた時、(効率とか考えなければ)やはり自明なだけで面倒なコーディングをする必要がある。

こういう「自明かつ面倒なコーディング」をやらなければいけなくなった時、「自動化したい」と思うのは自然な発想だ。Formuraは、まさにそのような思想で作られた、格子計算プログラム生成言語(というかフレームワーク)である。

本稿では、このFormuraを使ってみる。

  • その1 インストールとコンパイルまで ←イマココ
  • その2 一次元熱伝導方程式
  • その3 二次元熱伝導方程式
  • その4 反応拡散方程式(Gray-Scott系)

インストール

Formuraは(おそらくオリジナルの作者の趣味で)Haskellで書かれている。なので実行にはHaskellが必要だ。例えばMacOSでbrewを使うなら

brew install haskell-stack

Linux系なら

curl -sSL https://get.haskellstack.org/ | sh 

とかで入ると思う。
次に、Formuraをダウンロードして、セットアップしよう。

git clone https://github.com/formura/formura.git
cd formura
stack install

最後のstack installは、初回実行時にかなり時間がかかる。もし、この途中で「libtinfo.soが見つからない」と怒られたら、libncursesを入れることで解決する可能性がある。僕の場合は

sudo yum install ncurses-devel

としてから、再度stack installしたらいけた。

formuraは、$HOME/.local/binにインストールされるので、パスを通しておこう。

export PATH=$PATH:$HOME/.local/bin

パスが通ったか確認してみよう。

$ formura

Usage: formura FILES... [-o|--output-filename FILENAME] [--nc FILENAME]
               [-v|--verbose] [--ncopt ARG] [-f|--flag ARG] [--sleep SECOND]
  generate c program from formura program.

上記のようなメッセージが表示されたら正しくインストールされている。

Formura言語の記述

Formuraは、数値計算、特に規則格子計算を記述する言語だ。その言語仕様は公式リポジトリの「Download Formura Language Specification (pdf)」で参照できる。とりあえず必要なファイルは*.yamlファイルと*.fmrファイルだ。

YAMLファイルには、格子の情報を記述する。とりあえず格子間隔1、格子点64点の一次元系を定義しよう。後でGray-Scottのシミュレーションをする予定なので、gs.yamlというファイル名にしておく。

gs.yaml
length_per_node: [64.0]
grid_per_node: [64]

length_per_nodeが1ノードが担当する領域の長さ、grid_per_nodeが、1ノードが担当する領域のグリッド数だ。今回は1次元なのでそれぞれ要素数1のリストとして与えている。

さて、次にgs.fmrにFormura言語を記述する。拡張子はfmrとする。

gs.fmr
dimension :: 1
axes :: x

begin function u = init()
  double [] :: u = 0
end function

begin function u2 = step(u)
  u2 = u
end function

外見や、ベクトル、行列の扱いについてはFortran90ライクに見える。

最低限必要なのは

  • 次元の宣言
  • 軸の宣言
  • 初期化関数 init
  • 時間発展関数 step

の4種類だ。内容については次回説明するが、とりあえず

  • uという一次元配列を用意して0で初期化する関数init
  • uを受け取って、それをそのまま次のステップの値u2とする(つまり何もしない)時間発展関数step

を記述している。

YAMLとfmrファイルを作成したら、formuraに食わせる。

$ formura gs.fmr
Generating code...
Generate:
  gs.c
  gs.h
  run

ソースコードであえるgs.cgs.h、実行スクリプトrunを吐く。

これを実行するためのmain関数を書こう。FormuraはC言語を吐くが、趣味でC++で書く。

main.cpp
#include "gs.h"

int main(int argc, char **argv) {
  Formura_Navi n;
  Formura_Init(&argc, &argv, &n);
  Formura_Finalize();
}

先程作成されたgs.hをインクルードした上で、Formura_Initで初期化、Formura_Finalizeで終了する。MPIと似たインタフェースだ。

これをコンパイルする。

$ g++  main.cpp gs.c

C++とCのソースを混ぜてコンパイルしているので、たとえばclang++を使うと文句を言われるが、とりあえず気にしないことにする。

できたバイナリa.outを実行してみる。

$ ./a.out

エラーなく実行できれば成功である。何もしないプログラムなので、何も表示されない。

まとめ

格子計算プログラム生成言語Formuraをインストールし、使ってみた。まだインストールとコンパイルをしてみただけだが、次回以降、簡単なシミュレーションをしてみる予定である。

その2へ続く。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15