現在作成中です。 既に書いている内容も&color(#ff0000){大幅に変わる};可能性が高いです。 as of 2010-04-28 (&counter;) ------- #contents ------- * 担当教員 [#d810a8d4] 陰山 聡 * 演習日 [#e84fbb5c] - 2010.05.06 - 2010.05.13 * 概要と達成目標 [#dcc5c361] + 概要 ++ why f? (なぜFortran95言語か) ++ f && c (Fotran95とCの同じところ) ++ [演習]Hello, world. コンパイルと実行 ++ diff f c (Fotran95とCの違うところ) ++ wonderful f (Fotran95の素晴らしいところ) ++ practical f (Fotran95によるコーディングの実際) + 目標 ++ この「計算科学演習I」で扱うFotranソースコードが自由に読めること。 ++ 2次元拡散方程式を解くコードをFotran95言語の特性を活かして書けるようになること。 * はじめに [#rd9d9a92] // wiki の練習。コメントのテスト。この文字は見えないはず。見えたら異常。 ** エディタとコンパイラ [#oae90ba8] - Emacsのmajorモードをf90に設定すると便利(f95モードは用意されていない) -- ミニバッファでf90-modeと打つ (Esc-x f90-mode) -- 構文の開始と終了ペアリング入力が簡単。tabキー -- ^Jで整形改行 - scalar上でのコンパイルコマンドは pgf95 またはpgf90 - フリーのFortran95コンパイラ -- gfortran (gnu Fortran): http://gcc.gnu.org/fortran/ -- g95: http://www.g95.org/ ** Fortran90/95の歴史 [#rd9d9a92] - ''FORTRAN''(全部大文字の)という言語は存在しない。 --''Fortran90''や''Fortran95''という言語ならある。 - FORTRAN66。 --1966年に標準化。 - FORTRAN77 --1977年に標準化。 -- if/then/else -- 広まった - Fortran90 -- 1991年に標準化。 -- 大幅な改訂 - Fortran95 --F90からのマイナーバージョンアップ Fortran90はFORTRAN77とは大きく違う。違う言語と考えるべき。 ~| f95 - f90 | << | f90 - f77 | * why Fortran90/95? [#qfc92c34] ** 正しい理由 [#p0256e61] + 計算速度が速い -- スーパーコンピュータは速さが命 -- C/C++でもFortranと同じくらい速いコードは書けるが、遅いコードも書けてしまう。 -- 言語としての自由度の違い。自由度が高いとコンパイラが困る。最適化ができなくなる。 + 便利 -- 道具(言語)は目的にあったものを -- 数学的計算にはFortran90/Fotran95が適している --- '''For'''-mula '''Tran'''-slator -- 数値計算ライブラリの抱負な蓄積。Legacyなコード。財産。 ** 間違った理由 [#o19dac24] 『新しい言語を勉強するのは面倒だ。 FORTRAN77の何の不足もない。これでxx年やってきた。』 ・・・Legacyな人間。時代に2010-1977=33年遅れている。 ** Fortran90/95に対する偏見 [#u2f56714] 以下全てFORTRAN66/77と誤解している。 - 変数名は6文字までなんでしょう?・・・そんなことはありません。 - ソースコードは全部大文字なんでしょう?・・・そんなことはありません。 - ソースコードは固定形式(7列目から72列目まで)なんでしょう?・・・そんなことはありません。 - 構造体がないんでしょう?・・・あります。普通に使います。 - ポインタがないんでしょう?・・・あります。あまり使う必要はありませんが。 - 再帰呼び出しができなんでしょう?・・・できます。あまり使う機会はありませんが。 - 関数とデータをまとめてひとかたまりにする(クラス化する)ことなんてできないんでしょう?・・・できます。普通にやっています。 - データ/関数の隠蔽(カプセル化)ができないんでしょう?・・・できます。いつもしています。 - 演算子を自分で定義することができなんでしょう?・・・できます。いつもしています。 - 関数や演算子の多重定義ができなんでしょう?・・・できます。いつもしています。 ** Fortran90/95は現代のプログラミング言語である。 [#g3040af6] - スーパーコンピュータ向けの言語としては最先端 - 特に並列計算機には - 数値演算や計算機シミュレーションには最適な言語 ** まだ納得できないない?では例を一つ [#ra937520] 部屋の中の温度場の分布から平均気温を求めよう。 温度場を3次元float配列 f(nx,ny,nz)で表す。3つの整数nx, ny, nzは不定。 平均気温=全ての格子点(i,j,k)上でのfの値を足して格子点の総数で割る ** 【演習】 [#t9110993] 任意サイズの3次元単精度実数(浮動小数点数)配列を受け取り、 その平均値を返す関数をC言語(またはC++言語)で作れ。 - scalar上でのCコンパイラ=cc, gcc ** Fortran90/95ではこう書ける。 [#ube6e027] わずか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 ** 数式の表現が簡単な例(複素数) [#ada18727] $e^{i\pi} = -1$ つまり #ref(e_i_pi.jpg) をFortran95で書くと、 complex :: i = (0.0,1.0) real :: pi = 3.141593 print *,' exp(i*pi) = ', exp(i*pi) ** 例(行列の計算) [#h6f4d481] 行列のかけ算はFortran90/95ではmatmulという組み込み関数を使う。 行列の転置をとる組み込み関数transposeも用意されている。 したがって、行列A(例えば10行10列の2次元配列)の転置と別の行列Bの積を計算しそれを行列Cとする計算、つまり // C = {}^t\!A\, B #ref(matmul_a_transpose_b.jpg) をFortran90/95で書くと、 real, dimension(10,10) :: A, B, C C = matmul(transpose(A),B) と一行で書ける。 ** 例(級数) [#h6f4d481] 級数 #ref(series_one_forth.jpg) // \sum_{n=1}^\infty\,\frac{1}{i}\cdot\frac{1}{i+1}\cdot\frac{1}{i+2} = \frac{1}{1}\cdot\frac{1}{2}\cdot\frac{1}{3} + \frac{1}{2}\cdot\frac{1}{3}\cdot\frac{1}{4} + \frac{1}{3}\cdot\frac{1}{4}\cdot\frac{1}{5} + \cdots = \frac{1}{4} の最初の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次元ベクトル場のエネルギー) [#h2acd79c] 空間中に分布する磁場(3成分のベクトル場) Bx(100,100,100), By(100,100,100), Bz(100,100,100) の全磁気エネルギーを計算して出力するには、 print *,' energy = ', sum(Bx**2+By**2+Bz**2)/2 と一行(定義式そのもの)を書けば良い。 * diff f && c : C言語との比較によるFortran90/95入門 [#zf847c1d] ** 定番 hello, worldプログラム [#k5bb5231] C言語 #include <stdio.h> main () { printf("hello, world.\n"); } Fortran90/95 program hello_world print *, "hello, world." end program hello_world ** 【演習】 [#r664bdd2] + 計算機「scalar」 で、上のFortran90/95プログラムをエディタで入力し、 ファイル名hello_world.f95として保存せよ。 + ls -l コマンドでファイルを確認せよ。 + hello_world.f95 をコンパイルせよ。 -- pgf95 hello_world.f95 - Fortran90/95では標準入出力は組み込まれている(ヘッダファイルをインクルードする必要はない) - Fortran90/95では print *で標準出力へ。 - 行末にセミコロン不要。 - 文字列はダブルクォーテーションマーク(")で囲む。(C言語と同じ) - シングルクウォーテーションマーク(')でも同じ意味。(これはC言語と違う) ** 大文字・小文字 [#dfe20c0f] - Fortran90/95のソースコードではアルファベットの大文字と小文字は区別しない。 -- voltage と Voltage と VOLTAGE は同じ -- 文字列変数の中では区別される。 ** 予約語 [#r3a28ada] Fortran90/95には予約語が存在しない。 それが変数名かどうかコンパイラが賢く判断してくれる。 if (end==else) if=0 は文法的に問題ない。 ** コメント行の書き方 [#l593265a] C言語 /* この間がコメント */ Fortran90/95 ! 一行の中でこの文字以降がコメント( C++やJAVAの//と同じ) ** 型名 [#udeac7be] | 型 | 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 | 詳しくは後述 | ** 定数 [#ha3326c8] C言語 #define NX 100 Fortran90/95 integer, parameter :: NX = 100 ** 配列 [#rb6c9a8a] *** 1次元配列 [#p525880e] C言語 int array01[NX]; Fortran90/95 integer, dimension(NX) :: array01 *** 2次元配列 [#xa06a740] C言語 int array02[NY][NX]; Fortran90/95 integer, dimension(NX,NY) :: array02 *** 3次元配列 [#o2df7a6b] C言語 int array03[NZ][NY][NX]; Fortran90/95 integer, dimension(NX,NY,NZ) :: array03