実際に天文学の研究をするという観点からは、多くの場合に様々な言語を使う 必要に迫られる。というのは、観測的研究、理論的研究のどちらにしても、 (本当に「紙と鉛筆」だけでできる理論的研究の一部を別にすれば)計算機を使っ てデータ解析やシミュレーションをすることが必須であり、そのためのプログ ラムを作る必要がある。ところが、こういったプログラムは大規模・複雑なも のになってきており、一人でゼロから書けるものではなかなかない。何人もが 共同で作ったり、また、過去に別の人が作ったものを変更・改良して使うこと が普通である。このために、過去の資産が Fortran であれば Fortran が使え ないといけないし、C であればそれでなんとかする必要がでてくる。
この講義では Fortran を扱い、計算天文学 II では C++ を扱うことにする。 2 種類の非常に違う言語を短期間に扱うのは混乱を招く面もあることは否定し ないが、逆に言語1つだけしか知らないと、2番目を学ぶのは非常にハードルが 高いからである。2つの言語を一応理解していると、その間には共通点と相違 点があることが分かり、さらに他の言語を理解する必要ができた時にも類推が 効くようになる。
FORTRAN は、1950年代に開発された言語で、計算機言語としては、歴史が古い。進歩 の速い計算機に関しては、歴史が古いという事は、多くの場合、陳腐で劣る事を意味 する事が多い。事実、50年代或いはそれ以後開発された言語で、今日では使用されな くなった言語は非常に多い。そういった環境の中にあっても、FORTRAN は、色々な意 味で、優れた点を多く持った言語なので、様々な改良を加えられながら、今日まで、 科学計算用の標準的言語の一つとして、使われ続けている。その特徴としては、
なお、Fortran の言語仕様には、 Fortran 66, 77, 90 とほぼ 10年毎に大き な改訂が加えられてきた。この講義では、基本的には 77 に準拠するが、 90 での拡張をある程度取り入れた形でプログラムを書く。現在広く使われている のがその形であり、また計算機室のシステムで利用可能なのもそれだからである。
計算機の演算能力を最大限に発揮するには、計算機が直接理解できる機械語(アセン ブラ)でプログラムを書けば良いのだが、このためには、プログラムを書く人間の側 に多大の努力を要し、効率悪く、とても一般の人向きではない。そこで、FORTRAN 等、 人間が理解しやすい言語でプログラムを書き、それを機械語に翻訳させる作業(コン パイルという)を計算機自身にさせる訳だが、FORTRAN には、高速にしかも最適化され た機械語に翻訳する技法が進んだ形で取り入れられている。これらの理由から、 FORTRANは長い間多く利用され、それが更に、ライブラリを完備させる等、良い方向に フィードバックされて、より便利な道具として使われる理由となっている。
FORTRAN を使って計算をしたい時には、FORTRAN の言語で書かれた一つのファイルを 先ず作らなければならない。こういったファイルをプログラムと呼ぶ。例として、球 の半径が与えられた時に、球の表面積と体積を求める計算を考えよう。そのためのプ ログラムの例は、第章で、エディタを使ってのファイル作成練習で書い た、sphere.fである。念のため、下に掲げておこう 。
Program sphere Implicit NONE c constant: Real PI Parameter (PI=3.141593) c local variable: Real radius Real area, volume c begin: radius = 10.0 area = 4. * PI * radius**2 volume = area * radius /3. Write(*,*) 'radius:',radius Write(*,*) ' surface area =',area,' volume =',volume c end: Stop End
例.
a = 1.0 b = a + 1.0
演算 | FORTRAN | 例 |
加算 | x + y | |
減算 | x - y | |
掛算 | x * y | |
割算 | x/y | |
冪乗 | x**y | |
括弧 | (2.*(x + y))/(3.*(a + b)) |
Implicit NONE Parameter (PI=3.141593)がそうだ。最初の例は、そのプログラムで使用する変数は全て型宣言をしてから 使う事を宣言している。FORTRAN では、最初の文字によって、計算機が型を暗黙 のうちに解釈するという、便利なような恐ろしいような約束事がある。一見便利 なようなルールだが、プログラムを書き直したり、長いプログラムを書く時等、 使う変数をきちんと把握している方が、結局は便利である事の方が多い。 Implicit NONEをプログラムの頭で宣言しておくと、 型宣言していない変数をプログラム中で引用していたら、計算機が警告してくれる。
型 | FORTRAN | 大きさ |
整数型 | Integer | |
Integer*4 | ||
実数型 | Real | (有効数字7桁) |
Real*8 | (有効数字15桁) | |
複素数型 | Complex | (有効数字7桁) |
Complex*16 | (有効数字15桁) | |
論理型 | Logical | .true.(真)或いは .false.(偽) |
Logical*2 | ||
文字型 | Character*サイズ | サイズ分の長さの文字列 |
二番目の例のParameter文は、変数PIの値を指定している。式として 書いても同じ事だが、物理定数等このParameter文を用いて宣言すると、 値を直す時等、場所が決まっているから、便利である。
DIMENSIONの宣言は、良く使うであろう。 等を変数として、 使いたい時がある。この様な時、
DIMENSION y(10)の様に宣言すると、y(1), ... , y(10) が使えるようになる。引数が 二次元ならば、
DIMENSION y(i,j)の様にすれば良い。iとjは、それより前の Parameter文でサイズを宣言して おけば良い。
Write(*,*) 'radius:',radius Write(*,*) ' surface area =',area,' volume =',volumeが、WRITE文である。'radius:'はradius:と表示させる事を意味し、 カンマに続くradiusは、変数radiusの値を表示させる事を意味している。
if (code.eq.1) then ... else ... end if或いは次の様な更に細かい条件分岐も出来る。
if (code.gt.1) then ... else if (code.eq.1) then ... else ... end if
y = 0.0 Do i=1,10 y = y + a(i) End doiが10以下である限り繰り返すといった場合には、次の様なDo whileが便 利だ。
i = 1 Do while (i.le.10) y = y + a(i) i = i + 1 End do
Program sphere2 Implicit NONE c constant: Real RADIUS_INITIAL,MAX_RADIUS,DELTA_R Parameter(RADIUS_INITIAL=1.0,MAX_RADIUS=10.0) Parameter(DELTA_R=2.0) c local variable: Real radius Real area, volume c begin: radius = RADIUS_INITIAL Do while (radius .le. MAX_RADIUS) Call calculation(radius, area, volume) Write(*,*) 'radius:', radius Write(*,*) ' area =',area,' volume =',volume Write(*,*) radius = radius + DELTA_R End do Stop End Subroutine calculation(radius, area, volume) Implicit NONE c input: Real radius c output: Real area, volume c constant: Real PI Parameter (PI=3.141593) c begin: area = 4. * PI * radius**2 volume = area * radius /3. Return Endメインプログラムでは、半径を与えるだけで、計算はサブルーチンcalculation で行っている。そしてメインプログラムとサブルーチンとの間のやり取りは、メイン プログラム中のcall文で行う。その際、引数(radius,area,volume)は、 radius がメインプログラムから与えられ、areaとvolumeは、サブ ルーチンから計算の結果として、メインプログラムに返される。 それぞれの引数の型は、メインプログラムとサブルーチンの間で必ず一致させなけれ ばならない。但し、引数の名前は両者の間で異なっていても構わない。 この例に見るように、引数はメインプログラムからサブルーチンにも渡せるし、 逆にサブルーチンからメインプログラムにも渡せる。どちらからどちらに渡されてい るかは、一見して明らかな訳ではないので、上のサブルーチンcalculationの 例のように、コメントで注釈を附けておくと、便利である。 また、サブルーチンから、別のサブルーチンを呼ぶことも出来る。 サブルーチンはReturnとEndで終わるのが約束である。
Program sphere3 Implicit NONE c constant: Real RADIUS_INITIAL,MAX_RADIUS,DELTA_R c local variable: Real radius Real area, volume c begin: Write(*,*) 'Input RADIUS_INITIAL:' Read(*,*) RADIUS_INITIAL Write(*,*) 'Input MAX_RADIUS:' Read(*,*) MAX_RADIUS Write(*,*) 'Input DELTA_R:' Read(*,*) DELTA_R radius = RADIUS_INITIAL Do while (radius .le. MAX_RADIUS) Call calculation(radius, area, volume) Write(*,*) 'radius:', radius Write(*,*) ' area =',area,' volume =',volume Write(*,*) radius = radius + DELTA_R End do Stop End
Read(*,*)が、端末から変数を読み込ませるときに用いる文である。
Program sphere4 Implicit NONE c constant: Real RADIUS_INITIAL,MAX_RADIUS,DELTA_R c local variable: Real radius Real area, volume c file open: Open(Unit=2,File='Input.dat',Status='OLD') Open(Unit=3,File='Output.dat',Status='NEW') c begin: Read(2,*) RADIUS_INITIAL,MAX_RADIUS,DELTA_R radius = RADIUS_INITIAL Do while (radius .le. MAX_RADIUS) Call calculation(radius, area, volume) Write(3,*) 'radius:', radius Write(3,*) ' area =',area,' volume =',volume Write(3,*) radius = radius + DELTA_R End do Stop End
(*,*)のところが(2,*)となったため、入力は2番の論理装置から行なわれ る。その2番の論理装置がInput.datという名前の既製のファイルである事を 最初のOpen文が記述している。 Write文が、(3,*)であるから、出力は 3番の論理装置に対してなされる。 二つ目のOpen文は、同様に3番の論理装置がInput.datという名前の の新規のファイルである事を記述している。
Program sphere5 Implicit NONE c constant Integer N Parameter(N=2000) c local variable: Real radius Real area, volume integer i c file open: Open(Unit=2,File='Input.dat',Status='OLD') Open(Unit=3,File='Output.dat',Status='NEW') c begin: Do i=1,N Read(2,*,end=900) radius Call calculation(radius, area, volume) Write(3,*) 'radius:',radius,' area =',area,' volume =',volume End do 900 Write(*,*) 'number of data=', i-1 Stop Endこのプログラムで、N以上読み込みデータがあると、number of data として正しくない答えNを表示する。
FORTRAN | 意味 | FORTRAN | 意味 |
sqrt(x) | exp(x) | ||
log(x) | log10(x) | ||
sin(x) | asin(x) | ||
cos(x) | acos(x) | ||
tan(x) | atan(x) | ||
sinh(x) | cosh(x) | ||
tanh(x) | abs(x) | の絶対値 | |
int(x) | の整数部 | float(n) | 整数を実数に変換 |
max(x,y,z,...) | の最大値 | min(x,y,z,...) | の最小値 |
混合演算をしないように、と書いたが、実数xを整数に型変換するには、 int(x)を使い、整数xを実数に型変換するには、float(x)を 使う。
real function S(r) implicit NONE c constant: real PI parameter (PI=3.141593) c local variable: real r c begin: S=4.*pi*r**2 return end real function V(r) implicit NONE c constant: real PI parameter (PI=3.141593) c local variable: real r c begin: V=4./3.*pi*r**3 return endで定義して、メインプログラムからは、
Program sphere6 Implicit NONE c constant: Real RADIUS_INITIAL,MAX_RADIUS,DELTA_R c local variable: Real radius Real area, volume, S, V c begin: Write(*,*) 'Input RADIUS_INITIAL:' Read(*,*) RADIUS_INITIAL Write(*,*) 'Input MAX_RADIUS:' Read(*,*) MAX_RADIUS Write(*,*) 'Input DELTA_R:' Read(*,*) DELTA_R radius = RADIUS_INITIAL Do while (radius .le. MAX_RADIUS) Write(*,*) 'radius:', radius area =S(radius) volume=V(radius) Write(*,*) ' area =',area,' volume =',volume Write(*,*) radius = radius + DELTA_R End do Stop Endのように、外部関数を使う。FUNCTION 文は、メインプログラムの後ろにつけて、コン パイルするのが良いだろう 。
浦 昭二: FORTRAN入門(3訂版)(培風館)
森口繁一:JIS FORTRAN入門(第3版)上・下 (東大出版会)