HOME xyzzy download 書き込む

numerical-mode.l

数値計算ソフトの結果を GNUPLOT で表示する。

1. はじめに

Fortran や C で書かれた数値計算プログラムは伝統的に、ある決まった名前の入力ファイルを読み込み、 決まった名前の出力ファイルを吐き出すという不文律があります。 例えば、numeric.exe は 入力ファイル numeric.inp から パラメータを読み込み、結果を numeric.log に、 プロット用のデータを numeric.dat 吐き出します。 もちろん、プログラムが複雑になると、吐き出すファイルも多くなりますが、 基本的には事前に名前の決まったファイルを吐き出します。 これは多分メインフレームのバッチジョブに対応するためだったと思われます。現在はパソコンの パワーが飛躍的に増大したので、メインフレーム、ワークステーションを使わなくても数値計算ソフトを 走らせることが出来るようになりました。また、gcc, g77 のような優れたフリーの C, Fortran コンパイラー も win32 環境で動作します注1

この手のプログラムを走らせる場合、xyzzy を含む Emacs ライクなエディターで入力ファイルを編集し、 プログラムを 走らせ、結果を GNUPLOT で表示するというサイクルをとります。 これには以下の特徴があります。

  1. 入力ファイル名から、実行ファイル、出力ファイルを知ることが出来る。
  2. バックアップを取らないと以前のファイルは消えてしまう。
つまり、ファンクションキーを押すだけで、次の動作をするマクロがあれば、 これらのプログラムを便利よく走らせることが出来ます。
  1. 入力ファイル名から、実行するプログラムを決め、自動的に実行する。
  2. 自動的にバックアップを作成する。
  3. GNUPLOT を呼び出し、プロット用データをプロットする。
です。

numerical-mode.l はこの仕様を満たすマクロを簡単に 書くためのモードです。実際に使うにはソースを書き換える必要がありますが、書き換える範囲は 最小限になるように工夫してあります。まず、簡単な例を示し、それから、ソースの書き換え方を示します。

注1:cygwin, MinGW などのプロジェクトがあります。cygwin の方が先行していて、インストーラー任せでインストールできます。

2. 準備

2.1. gnuplot のインストール

gnuplot はsourceforge.net から、ダウンロード出来ます。gp400win32.zip (7 月 1 日現在)をダウンロードして適当なディレクトリに 解凍してください。/bin の中にある。wgnuplot.exe をダブルクリックするとコンソールが現れます。 表示が小さくて読めないときはマウスコンソール上で右ボタンを押すと choose font というメニューが 現れますので、それをクリックしてフォントサイズを大きくして下さい(例えば 14 pt)。 表示の変更は Update Wgnuplot.ini を選択して保存しておきます。 コンソールから plot sin (x) と入力してみてください。 サインカーブが描かれるはずです。詳しい使い方は付属の help または、 gnuplot homepageを参考にしてください。 日本語のページでは、 などが比較的新しい情報を取り入れています。

wgnuplot.exe と同じディレクトリに入っている pgnuplot.exe は、他のプログラムから gnuplot にコマンドを渡すのに使います。

環境変数 GDFONTPATH をフォントのあるディレクトリ(例えば、"C:\WINDOWS\FONTS\")に設定しておくと png ファイル (portable network graphics) にイメージを書き出すときにそのディレクトリにある TrueType (*.ttf) フォントと Adobe Type 1 (*.pfa) フォントが使用できます。

2.2 numerical-mode.l のインストール

以下の手順でインストールします。
  1. まず、ダウンロードした numerical.lzh を解凍します。解凍すると以下の8つのファイルが生成されます。
    numerical-mode.l
    マクロ本体
    edit-inp.l
    入力ファイル編集補助マクロ
    bullet.exe, bullet.c, bullet.inp
    弾道をシミュレートするプログラムの実行ファイル、ソースコード、入力ファイル。
    lorentz.exe, lorentz.c, lorentz.inp
    Lorentz attractor を描くプログラムの実行ファイル、ソースコード、入力ファイル。
  2. bullet.exe, lorentz.exe を適当なディレクトリ(例えば C:\usr\bin\) に保存します。
  3. bullet.inp, lorentz.inp はそれぞれ別のディレクトリに保存します。 (例えば C:\usr\bullet\ と C:\usr\lorentz\)
  4. numerical-model.l をエディターで開いて以下の編集を行います。
  5. 書き換えた、numerical-mode.l を /site-lisp に保存して、バイトコンパイルします。
    (byte-compile-file "./site-lisp/numerical-mode.l")

  6. .xyzzy に次の2行を加えます。
    (setq *auto-mode-alist* (acons "\\.inp$" 'ed::numerical-mode *auto-mode-alist*))
    (autoload 'ed::numerical-mode "numerical-mode" t)
  7. ダンプファイルを再作成します。
以上でインストールは終了です。

3. テスト

bullet.exe, lorentz.exe は MinGW 版の gcc を用い、次のようにコンパイルしました。
gcc -o foo.exe foo.c -O
MinGW 版を用いたので特別な dll は必要なくそのまま動作すると思います。

3.1. bullet

xyzzy で bullet.inp を開いて F10 を押してください。 bullet.exe が起動して、 図1にあるようなプロットが得られれば成功です。戦艦大和の 46 cm 砲の砲弾はこんな感じで飛ぶと思われます。 bullet.exe は空気抵抗、重力加速度の高度依存性を考慮しています。ただし、コリオリの力は考慮していません。 発射角度が 45 度より若干大きいのは高空の方が空気抵抗が少ないため射程が延びるためです。bullet.inp を適当に 書き換えて遊んでみてください、history.txt に bullet.inp と bullet.log の履歴が新しい順に保存されます。 また、history.txt の内容はバッファ * history *に表示されます。

図1:46 cm 砲の弾道

3.1. Lorentz attractor

xyzzy で lorentz.inp を開いて F10 を押してください。 lorentz.exe が起動して、 図2にあるようなプロットが得られれば成功です。history.txt, * history * については 3.1. の 場合と同様です。Lorentz attractor についての解説は 科学技術と芸術(1):数理と造形FORTRANプログラミング初級編 などを見てください。

図2:Lorentz attractor

4. numerical.l に数値計算プログラムを登録する

新しいプログラムの登録は、マクロ defnumeric を用います。 新しい関数の定義は、ソースコードの (mark 2) -- (mark 3) の間に書いてください。 関数を定義したら、必ずバイトコンパイルして、ダンプファイルを再作成して下さい。

defnumeric の書式は以下の通りです。

defnumeric
書式: (defnumeric name (exec-file inp-file backup-file-1 ....backup-file-n) body)
例として、bullet と lorentz の定義を載せます。
;;; defining bulllet 
(defnumeric bullet ( "c:/usr/bin/bullet.exe" "bullet.inp" "bullet.log")    ; (mark 2a)
    (with-vars-in-log ("bullet.log"
           (v0 "initial +speed += +")
           (angle "firing +angle += +")
           (vf "flight +distance += +"))
      (with-plot ("bullet.plt")
	("re=6.37e6~%")
	("set title \"trajectory of bullet\\n\\~%")
	("v0=~F (m s-1), firing angle = ~F (degree), range of deposit = ~F (m)\"~%"
		v0 angle vf)
	("set size ratio -1~%")
	("set xlabel \"distance/m\"~%")
	("set ylabel \"height/m\"~%")
	("plot \"bullet.dat\" us 2:3 t \"trajectory\"  w l 1,\\~%")
	("sqrt(re*re-x*x)-re t \"earth surface\" w l 5~%"))))
 	   
;;; defining lorentz
(defnumeric lorentz ("c:/usr/bin/lorentz.exe" "lorentz.inp" "lorentz.log")  ; (mark 2b)
    (with-vars-in-log ("lorentz.log" (a "a += +")(b "b += +")(c "c += +"))
       (with-plot ("lorentz.plt")
	 ("set title \"Lorentz's attractor\\n a = ~A, b = ~A, c = ~A\"~%" a b c)
	 ("set ticslevel 0~%")
	 ("set xlabel \"X\"~%")
	 ("set ylabel \"Y\"~%")
	 ("set zlabel \"Z\"~%")
	 ("set view 78,221~%")
	 ("splot \"lorentz.dat\" us 2:3:4 t \"trajectory\" w l 1~%"))))
例を見ると分かるように、自分で書く必要のある部分は、gnuplot へ渡すコマンドだけです。 これには、2つのマクロ with-vars-in-logwith-plotを使います。with-vars-in-log はログファイルから数値を読みとるマクロで、一方、with-plot は gnuplot にコマンドを 渡すためのマクロです。 以下に使用法を説明します。
with-vars-in-log
書式: (with-vars-in-log (log-file-name (var1 regexp1 char1)...... (varn regexpn charn)) body)
with-plot
書式: (with-plot (plot-file) (command1)...(commandn))
注2:正規表現については以下のリンクを参照してください。

5. デフォルトのキーマップ

次の表に デフォルトのキーマップ、関数名、機能を挙げます。
キー 関数 機能
F10 numerical-choice 入力ファイル名にあわせて数値計算プログラムを実行し、その結果を gnuplot で表示します。
Alt-p g-png ミニバッファからファイル名を入力し、 プロットを PNG(Portable Network Graphic) ファイルとして書き出します。
Alt-o g-auto autoscale にして再描画します。
Alt-r g-range x-range, y-range をミニバッファから入力して再描画します。
Alt-q end-plot gnuplot を終了します。

7. その他のカスタマイズ

次の表に示す3つの変数が、export されています。
これらの変数の値は本体をコンパイルしなおすことなく .xyzzy(または siteinit.l)に記述することで変更できます。この種の変数の変更の方法は xyzzy の音 - モード毎の設定 を見てください。

変数 記述
*gnuplot-command* pgnuplot をフルパスで指定します。
*numerical-mode-map* キーバインドを指定します。
*numerical-mode-hook* 例えば入力ファイル編集用の関数などを追加します。

入力ファイルの編集補助マクロの例として edit-inp.l を作ってみました。 使い方は以下の通りです。

  1. edit-inp.l を /site-lisp にコピーし、バイトコンパイルし、ダンプファイルを再作成します。
  2. .xyzzy に次の1行を加えます。
    (add-hook 'ed::*numerical-mode-hook* #'(lambda () (require "edit-inp")))
  3. 入力ファイル (*.inp) を開いて "Alt-v" を押すと、それぞれのパラメータについて値をミニバッファ から値を聞いてくるので、変更しない場合はそのままリターンを押し、変更する場合は値をミニバッファに 入力します。
キーバインディングの変更などは edit-inp.l のソースを見てください。 また、自分の入力ファイルの書式にあわせて便利なマクロを作ってください。

6. おわりに

数値計算プログラムを xyzzy 上で動かす汎用マクロを書いてみました。いままで、この種のマクロは 使用者が自分の目的にあわせて個別に書くのが一般的で、汎用性はありませんでした。
このスクリプトでは、マクロ difnumeric, with-vars-in-log, with-plot を使うことにより 数値計算プログラムと gnuplot が簡単に連結できるようにしました。 このマクロが数値計算プログラム+xyzzy ユーザーのお役に立てれば幸いです。