現在(2018-04-05 (木) 13:09:14)作成中です。 既に書いている内容も大幅に変わる可能性が高いので、注意。 as of 2023-06-01 (木) 01:54:42 (222)
陰山 聡
Fortran90はFORTRAN77とは大きく違う。違う言語と考えるべき。
| f95 - f90 | << | f90 - f77 |
『新しい言語を勉強するのは面倒だ。 FORTRAN77の何の不足もない。これでxx年やってきた。』
・・・Legacyな人間。時代に2010-1977=33年遅れている。
以下全てFORTRAN66/77と誤解している。
部屋の中の温度場の分布から平均気温を求めよう。
温度場を3次元float配列 f(nx,ny,nz)で表す。3つの整数nx, ny, nzは不定。
平均気温=全ての格子点(i,j,k)上でのfの値を足して格子点の総数で割る
任意サイズの3次元単精度実数(浮動小数点数)配列を受け取り、 その平均値を返す関数をC言語(またはC++言語)で作れ。
わずか4行。
real function mean_value(f) real, dimension(:,:,:) :: f mean_value = sum(f) / (size(f,1)*size(f,2)*size(f,3)) end function mean_value
$e^{i\pi} = -1$ つまり
をFortran95で書くと、
complex :: i = (0.0,1.0) real :: pi = 3.141593 print *,' exp(i*pi) = ', exp(i*pi)
行列のかけ算はFortran90/95ではmatmulという組み込み関数を使う。 行列の転置をとる組み込み関数transposeも用意されている。 したがって、行列A(例えば10行10列の2次元配列)の転置と別の行列Bの積を計算しそれを行列Cとする計算、つまり
をFortran90/95で書くと、
real, dimension(10,10) :: A, B, C C = matmul(transpose(A),B)
と一行で書ける。
級数
の最初の1000項の和を求めるプログラムも、式をそのまま書けばいい。まさにFormula Translation。
integer, parameter :: nterms = 1000 real, dimension(nterms) :: x, y, z integer :: i do i = 1 , nterms x(i) = 1.0 / i y(i) = 1.0 / (i+1) z(i) = 1.0 / (i+2) end do print *,'ans = ', sum(x*y*z)
空間中に分布する磁場(3成分のベクトル場)
Bx(100,100,100), By(100,100,100), Bz(100,100,100)
の全磁気エネルギーを計算して出力するには、
print *,' energy = ', sum(Bx**2+By**2+Bz**2)/2
と一行(定義式そのもの)を書けば良い。
C言語では
#include <stdio.h> main () { printf("hello, world.\n"); }
Fortran90/95では
program hello_world implicit none print *, "hello, world." end program hello_world
さきほど作ったhello_world.f95のメッセージ("hello, world.")を自由に変え、 コンパイル&実行せよ。
Fortran90/95には予約語が存在しない。 それが変数名かどうかコンパイラが賢く判断してくれる。
if (end==else) if=0
は文法的に問題ない。
C言語では
/* この間がコメント */
である。C99では // から行末までもコメントとなった。
Fortran90/95では
! 一行の中でこの文字以降がコメント( C99やC++、JAVAの//と同じ)
型 | C ( C99 ) | Fortran90/95 | 補註 |
文字 | char | character | |
文字列 | char[n+1] | character(len=n) | nは文字長 |
整数 | int | integer | integer(kind=4)でも可 |
実数 | float | real | real(kind=4)でも可 |
倍精度実数 | double | real(kind=8) | kindの整数はシステム依存 |
「長い」整数 | long | integer(kind=8でも可) | kindの整数はシステム依存 |
bool | ( _Bool ) | logical | 値は .true. または .false. |
複素数 | ( _Complex ) | complex | |
構造体 | struct | type | 詳しくは後述 |
C言語
#define NX 100
Fortran90/95
integer, parameter :: NX = 100
C言語では変数の宣言はブロックの先頭にまとめて置く。(C99やC++はもっと自由だが。) Fortran90/95でも同じ。
Fortran90/95ではimplicit noneを省略すると「暗黙の型宣言」をしたことになる。 暗黙の型宣言とは、次の6つのアルファベット i,j,k,l,m,n で始まる変数は整数である等のルールである。 バグが入りやすいので、暗黙の型宣言は使わない方が良い。 &color(#ff0000){Fortran90/95プログラムでは常にimplicit none宣言をすること。}
宣言したつもりのない変数を間違って使っていても気がつかない可能性がある。 例えば、次のプログラムにはバグがある。すぐに見つけられるか?
program use_implicit_none integer :: fresh_meat flesh_meat = 100 ! yen print *, "today's price = ", fresh_meat end program use_implicit_none
上のプログラムをuse_implicit_nene.f95というファイルに書き込み、コンパイル&実行せよ。
今作ったuse_implicit_nene.f95の2行目(program ...の次の行)に implicit noneと書いてから、コンパイルせよ。
C言語
int array01[NX];
メモリ上に、array01[0], array01[1], array01[2], ..., array01[NX-1]と並ぶ。
Fortran90/95
integer, dimension(NX) :: array01
メモリ上に、array01(1), array01(2), array01(3), ..., array01(NX)と並ぶ。
配列のインデックスは1から始まる。
大きさNXの1次元整数配列array_01を作り、 各要素に1,2,3,...,NXを代入した上で、 全要素の和をとるFortran90/95プログラムを書け。
C言語
int array02[NY][NX];
Fortran90/95
integer, dimension(NX,NY) :: array02
C言語
int array03[NZ][NY][NX];
Fortran90/95
integer, dimension(NX,NY,NZ) :: array03
行末に&をつけると継続行
a = b + c + & d + f
セミコロンは改行と同じ
tmp = right right = left left = tmp
と
tmp = right; right = left; left = tmp
は同じ。