Windows10でFORTRANを動かさねばならない(中)


2017年 06月 09日

プログラムの内容の詳細は書く訳にいかないのだが、技術計算で、電磁気学に関するシミュレーションである。
数学的には、複素関数、複素級数、偏微分(マックスウェルの方程式)などが使われている。
たぶん今だったら、MatLab(Octave)でちょっと書けば済みそうな内容であるが、困ったことに内容が分からない。

日々科学技術計算をやっている訳ではないので、どうなるか分からないが、まあ調べれば何とかなるのではと思った次第である。
科学技術計算とかいってずいぶん難しいことをやっていると予想して勉強してから行くと、ほとんど科学技術とは無縁のプログラムであることが多いので、たぶんこれも大丈夫と予想したのであった。
それでも、一応、いざというときのために、関連情報などをネットで軽くは調べておいた。

このくらい古くなると、作ったときの資料も無ければ、作った人も居ない。既に彼方の世界の人になっている。
でも、ソースプログラムがあるから恵まれているほうである。
ソースプログラムが無い移植などの仕事もあるのだが、そういうのに比較すれば易しい。(比較がオカシイかも)
かなり面倒な計算をしているのだが、詳細な計算内容はとても追いかけるのは無理で、核心部分はブラックボックスのままであるが、それでも移植は可能であり、全く同じ動作をするかを確認する手段を考えて、引き受けた。

以上は、元のプログラムに何も問題がなければ、全く同じ動作をすれば移植のテスト完了となるのであるが、世の中そんなに甘くないのである。

プログラムは9本に分かれていて、技術計算をいっぱいしているのは2本だけである。
ある特殊な装置の電磁波の影響を計算するプログラムで、水平方向と垂直方向で別々のプログラムに分かれている。
垂直方向が5本、水平方向が4本の構成である。
計算以外のプログラムは、入力データを作るためなのだが、昔々のプログラムなので全てCUIになっている。

まずはコンパイルエラーを取るのだが、ワーニングがかなり出てうっとうしい。
コンパイル時にワーニングを出なくすることは可能だが、問題があったときに大事なワーニング情報を見失う可能性がある。
それで、ワーニングが出なくなるようにするFORTRANのソースコード・コンバーターをちょっとPythonで書いた。

実際のコンパイルオプションはこんな感じである。
gfortran -Wall -pedantic -std=f95 -fbounds-check -fall-intrinsics -Wuninitialized
-ffptrap=invalid,zero,overflow -o HOGE.exe HOGE.for
FORTRANのコンパイラオプションを決めるのに、東京大学のFortranデバッグオプションのページを参考にした。
まだFORTRANをどんどん使っている研究室があるんだ。

コンパイルが済んだら、とりあえず走らせてみるのだが、特殊な技術計算用のプログラムなので、データを用意するのが困難なので、データをファイルでもらって、それを読み込んで走らせることにした。

最初は、実行時エラーが出てしまった。
変数に値をセットする前に参照していると叱られた。
つまり、配列の初期化がされていない。
これがやたらに多かったのだが、昔のFORTRANの一部には、配列宣言をしたら初期化も自動で行われるもの(コンパイラのオプション指定)もあったためだろう。
ということで、初期化されていない配列の初期化をかなり行った。

一応、初期化を済ませたら、計算処理プログラムが何とか走り出した。
コンパイル時のオプションもどんどん減らして、最終的にはソースとオブジェクトの指定だけまで減らした。
やれやれである。

入力データを、まだ旧ソフトが動くコンピュータ上で実行してもらい、入力データと出力データをもらって、移植したプログラムでも実行し、2つの出力ファイルを比較した。
完全一致したら、移植が完璧ということになる。
出力ファイルはテキストファイルなので、ファイル比較を行い、一文字も差がないことを確認すればよい。
もし、旧プログラムにバグがあれば、バグも完全に再現できているという素晴らしい移植ということになる。

技術計算なので、どうしても数値計算誤差がでてくる。
計算結果は固定小数点数で、有効数字も3,4桁程度であるので、少々の計算誤差があっても、結果は同じになる。
それでも、2つ差異が出てしまった。

1つは、0.00と-0.00の差である。
0に非常に近い値のとき、計算誤差により正になったり負になったりする。
これは値としては同じと考えられるので、OKとした。

計算結果の最後の1行が出たり出なかったりした。
これは、リミットの計算を計算誤差を無視して、単に不等号で判断していたのが原因で、ちょっと余裕をもたせるようにして対処した。

これで、同じ入力データを新旧のプログラムで走らせた結果の2つの出力ファイルが一致したことになる。
とりあえず移植完了。

移植以外に、いくつかの機能UPの要望があったのだ。
どれも比較的簡単なものと思って気楽に引き受けたのだが、思わぬ展開になるのであった。

次回につづく。