ver. 2019/05/10 Fortran90の基本事項大文字と小文字は区別しない自由形式：一行132文字まで記述(コンパイルオプションで撤廃できる) (固定形式：FORTRAN77では何文字目から書くかが指定されていた)一行に一文を記述プログラムは上から順番に実行される;を使うことで一行に複数文を書くことも可能。 ！ aにゼロを代入、bにゼロを代入a=0; b=0 ! 以降は行末まではコメント文としてコンパイル時には無視される。一行が長くなって複数行にまたがる場合は一行目最後に＆次の行の頭にも&を置いても良いa = 1.0d0 + 2.0d0 + 3.0d0 + 4.0d0 + & &  5.0d0 + 6.0d0 + 7.0d0 + 8.0d0 + & &  9.0d0 + 10.0d0プログラムの基本構造PROGRAM プログラム名称宣言文 (IMPLICIT NONE宣言、変数宣言)実行文END  PROGRAMプログラム名称IMPLICIT NONEは、暗黙の変数型を使用せず、全ての変数の型を明確に指定する文。(使うことを推奨)暗黙の型宣言とは、IMPLICIT NONEを使わない場合FortranではIMPLICIT REAL*8(a-h, o-z)となりa〜h、o〜zで始まる変数・定数は倍精度実数型、その他のi〜nで始まる変数・定数はデフォルト型の整数型を使う方法が過去に広く使われていた(非推奨)型記述方法推奨されない記述方法
REAL*8とCOMPLEX*16はよく見かける。DOUBLE  PRECISIONは推奨されるがあまり見かけなし。変数名：英数字とアンダーラインが使える。英字から始まる31文字までの名前変数の宣言例INTEGER :: a REAL*8 :: b, c !初期値入力DOUBLE PRECISION :: d=0.0D0 COMPLEX(kind(0d0)) :: dt1 COMPLEX(kind(0d0)), PARAMETER :: iunit = (0.0d0, 1.0d0)  !プログラム中で値を変更しない変数(定数)にはパラメター属性をつける。文字型変数の宣言例
変数型について整数型：4バイト(32ビット)，2進数でメモリに格納。最大値2³¹-1まで単精度実数型：4バイト、10-³8~10³8，約7桁の精度(符号、指数と仮数部に格納) 3.5, 1.0e0, -1.0e5 (-10000)などと表示(eのあとは指数部)倍精度実数型：8バイト、10 -388~10 388 約16桁の精度3.5d0, 1.0d0, 1.0d-5 (0.00001)などと表示(dのあとは指数部)単精度複素数型：8バイト、実部と虚部が単精度実数型倍精度複素数型：16バイト、実部と虚部が倍精度実数型論理型：  .TRUE.または .FALSE.  (T,FでもOK)物理の計算では実数と複素数型では基本的に倍精度のものを使う。 ○四則演算(+, -,*, /)、累乗は**で表す。同じ型の演算は同じ型となる。(整数型/整数型は整数型) a = 5 / 2            !  aは2となる。  2.5にしたい場合は 5.0/2.0とする違う形の演算は型変換が行われる(整数と実数の演算は実数に、実数と複素数の演算は複素数に) α=4**3　！ 4の三乗、αは64となる○代入文変数に値を代入するには=を使う(数学の等号ではない) a = 5 / 2.0       ! 倍精度実数型のaに5/2.0の計算結果(2.5)を代入i = i + 1        ! iを1増やす。(再帰代入)
○DOループ文の使い方
基本例1 （sum（初期値0）にN回1を足す） !D0ループで足し算をする場合は初期値にゼロを代入するsum = 0 DO i = 1, N sum = sum + 1 END DO基本例2 （sum（初期値0）にiが1～Nまで増える間、3回ごとにiを足す） sum = 0 DO i = 1, N, 3 sum = sum + i END DO補足説明：  インクリメントDOループを１つずつ変数が増えながら行うのではなく、この場合は３つずつ増えて行く。つまり、i=1, 4, 7, 10, …の様に増えて行く事に注意。
○標準入出力(READ/WRITE/PRINT文の使い方)
基本例(コマンドラインから読み込んだ値をhogeに代入し、hogeをディスプレーに出力） READ(*,*) hoge WRITE(*,*) hoge または PRINT *, hoge補足説明：　WRITE文の２つの＊（星印）の意味1つ目の＊はIO（ファイル装置番号）を指定する為に使う（後述） ２つ目の＊はFORMAT（データの型）を指定する為に使う何も考えずにインタラクティブに作業するのであれば、WRITE(*,*)あるいはPRINT *,を使う○配列（ベクトル）の扱い方型宣言基本例の行列DOUBLE PRECISION :: α(1:5),B(1:4,1:3) ! αは5つの要素を持つ配列、Bは4x3 DOUBLE PRECISION :: a(5), B(4,3)  !としてもよいDOUBLE  PRECISION,  DIMENSION(1:10)  :  p,q,r,s   !  p,q,r,sは10つの要素を持DOUBLE PRECISION :: p(1:10), q(1:10), r(1:10), s(1:10)  !としてもよいつ配列その他の例DOUBLE PRECISION :: a(-2:2) a(-2)，a(-1)，a(0)，a(1)，a(2)の5つの要素を持つ倍精度実数型配列を定義初期値設定!配列Lの全ての成分が0 DOUBLE PRECISION :: L(1:5)=0.0D0 INTEGER :: L2(1:5) = (/1, 2, 3, 4, 5/)  !配列L2の各要素の初期値を設定基本例（N次元配列α,の全要素に0を代入） DO i = 1, N a(i)=0.0D0 END DO補足説明：当然、0以外の要素の代入・演算も可能DOループを使わずにa(1:N) = 0.0D0としてもよい。また、異なる配列の違う添字を持つ要素の代入・演算も可能DO i = 1, N a(i)=b(i+3) END DO DOループを使わずにa(1:N) = b(4:N+3)としてもよい。配列関係の組み込み関数SUM配列の和を計算c = SUM(a(1:10))     ! a(1)からa(10)までの和をcに代入MAXVAL/MINVAL 配列の要素の最大値あるいは最小値を返すc = MAXVAL(a(1:N))   !  a(1)からa(N)の中での最大値をcに代入d = MINVAL(a(1:N))     !a(1)からa(N)の中での最小値をdに代入組み込み関数DOT_PRODUCT 2つの1次元配列の内積を計算c = DOT_PRODUCT(a(1:N),b(1:N))  ! aとbの内積をcに代入整数型、実数型、複素数型いずれの場合も内積を計算するため複素数型の場合はCONJG(a(1:N))とb(1:N)の積が計算される。宣言時に配列の大きさに変数を使いたい場合は PARAMETER 属性あるいはサブルーチンならINTENT(IN)属性が必要(プログラム中で値が変更できなくなる) INTEGER, PARAMETER :: N = 100 DOUBLE PRECISION :: A(1:N), B(1:N), C(1:2*N)コンパイル時に配列の大きさが決まらない場合(実行時配列) INTEGER :: N REAL*8, DIMENSION(:), ALLOCATABLE :: a  !サイズを指定せずに宣言READ(*,*)  N ALLOCATE( a(1:N) )  ！ aの配列を割り当てる!ここで計算をするDEALLOCATE（a）    !  aの配列をメモリから開放する
○行列の扱い方
基本例（N×N行列B 1の全要素に0を代入） DO i = 1, N DO j = 1, N B(j,i)=0.0D0 END DO END DO補足説明：２重ループの構造上、内側のループが優先的に変化する。 Fortranでは多次元配列はB(1,1), B(2,1), B(3,1), ..., B(N,1), B(1,2), B(2,2), ...の順番にメモリに格納される (C言語では逆)。この順に演算をしたほうがキャッシュミスが少なくなる。 DOループを使わずにB(1:N,1:N) = 0.0D0としてもよい。行列の組み込み関数MATMUL行列の積を計算c(1:N,1:K)= MATMUL(α(1:N,1:M), b(1:M,1:K)) ! ａとｂの積をｃに代入TRANSPOSE行列の転置を計算b(1:N,1:N) = TRANSPOSE(a(1:N,1:N))  !  bにaの転置行列を代入行列の出力DO文を使う (5 x 5行列Aの場合) DO i = 1, 5 WRITE(*,*) (A(i,j), j = 1, 5) END DO (A(i,j),j=1,5)のj(整数型変数)は展開されてA(i,1), A(i,2), A(i,3), A(i,4), A(i,5)となる。行列のサイズが大きい場合は標準出力に出しても読めないので、一部だけ出力したり、ファイルに出力して必要な処理をする。 ○型変換整数の実数化、実数の整数化基本例（iの値をaiと実数化、aの値をiaと整数化） ai=DBLE(i)         ! iを倍精度実数型に変換ia=INT(a)補足説明：数値関数参照！ aを整数型に変換複奏数の実部、虚部取り出し基本例rez = DBLE(z) ！複素数zの実部を(倍精度)実数型rezに代入imz = AIMAG(z)！複素数zの虚部を(倍精度)実数型imzに代入2つの実数を実部と虚部とする複素数を作るz = (2.0d0, 1.0d0)    !複素数に特定の数値を代入( zに2.0+iを代入) iunit = (0.0d0, 1.0d0)  !予めプログラムの最初で虚数単位を定義z = a + b * iunit !複素数zにα+ bi (αとbは実数型)を代入あるいはz = DCMPLX(a,b) ！ aとbが倍精度実数型の場合○組み込み関数
数値関数
補足説明：角度の単位はラジアン単位なので注意（180°=пラジアン）
OIF文の使い方
基本例1 （iの値が0の時は0を、 1以上の時は1を、それ以外（つまり負の値）の時は-1を加える) IF (i .EQ. 0) THEN i = i ELSE IF (i .GE. 1) THEN i = i + 1 ELSE i = i - 1 END IF補足説明：  関係演算子
:AがBと等しい時（A=B）に真:aがbと等くない時（a≠b）に真
基本例2　実行する文が短い場合はThenも省略して一行で書くことも可能delta = 0 IF (i .EQ. j) delta = 1                 ! i=jであればdeltaに1を代入
○IF文によるDOループの制御
基本例1    DO文で終了条件を書かない (EXIT文でループを抜ける) x = 0.0d0 DO x = x + 0.10d0 y = x**2 PRINT *, x, y IF( x .GT. 1.0d0) EXIT      ! x>1ならD0ループから出る条件が満たされないとプログラムは終了しないので端末からCtrl-Cで強制終了する。基本例2 特定の条件のときはDOループを実行しない(CYCLEでDOループの頭に戻る) DO i = 1, N IF ( i .EQ. 7 ) CYCLE     ! iが7のときは戻ってi=8の処理に移る。 !ここにｉが７以外のときの計算を書く。 END DO基本例3 入れ子(ネスト)になる場合はDOループに名前をつけるLOOP1: DO i = 1, N LOOP2: DO j = 1, N IF( i .EQ. j ) CYCLE LOOP2 END DO LOOP2 END DO LOOP1 IF-END IF文にも同様に名前をつけることができる。 ○論理演算
例： IF(A.EQ.B.AND.B.GT.C) THEN IF(.NOT.A.EQ.B) THEN IF(A.EQ.B.EQV.B.GT.C) THEN : AとBが等しく、BがCより大きい時真: AとBが等し無い時真(A.NE.Bと同じ) : AとBが等しく、BがCより大きい時真、またAとBが等しく無く、BがC以下の時真
○関数副プログラム
関数を定義することで組み込み関数と同じように使うことができる。関数がどの型の変数を返すかは関数の中で定義する。(多次元)配列を返すこともできる。基本例：  f(x) = 4x 3 - 5x を関数副プログラムとして定義、主プログラムの中に関数副プログラムを置く場合(内部副プログラム) PROGRAM  EXAMPLE2 IMPLICIT NONE DOUBLE PRECISION :: x x = 0.0d0 DO PRINT *, x, Func(x) x = x + 0.10d0 IF( x .GT. 5.0d0) EXIT END DO CONTAINS FUNCTION Func(x) ! 関数見出しDOUBLE PRECISION, INTENT(IN) :: x  !宣言部DOUBLE PRECISION :: Func  !関数の型を宣言するFunc = 4.0 * x**3 - 5.0 * x     !実行部RETURN END FUNCTION Func END PROGRAM EXAMPLE2関数に受け渡される引数に INTENT(IN)属性をつけることで関数内でこの値が変更できないようにできる。(推奨)基本例2: END PROGRAMの後に関数副プログラムを置く場合(外部副プログラム) PROGRAM  EXAMPLE2 IMPLICIT NONE DOUBLE PRECISION :: x DOUBLE PRECISION :: Func x = 0.0d0 DO !関数副プログラムの型宣言が必要PRINT *, x, Func(x) x = x + 0.10d0 IF( x .GT. 5.0d0) EXIT END DO END PROGRAM EXAMPLE2 !関数見出しFUNCTION Func(x) DOUBLE PRECISION, INTENT(IN) :: x  !宣言部DOUBLE PRECISION :: Func       !関数の型を宣言するFunc = 4.0 * x**3 - 5.0 * x      !実行部RETURN END FUNCTION Func RETURN文は関数やサプルーチンの処理を中断してその段階での値が関数やサプルーチンを呼び出したプログラムに返される。プログラムの末尾の場合は省略してもよい。
○サブルーチン副プログラム
関数副プログラムとほぼおなじ。違う点は・値を返さない(型がない) ・引数として(複数の)値を返すことができる• CALL文で呼び出す・サブルーチン副プログラムは1つの実行文だが関数副プログラムは実行文にはならない）基本例PROGRAM  EXAMPLE2 IMPLICIT NONE DOUBLE PRECISION :: x, y x = 0.0d0 DO CALL  Func(x,y)       !  CALL文でFuncサブルーチンを呼び出しPRINT *, x, y x = x + 0.10d0 IF( x .GT. 5.0d0) EXIT END DO !CONTAINS以下に副プログラムを列挙CONTAINS 11 !サブルーチン見出しSUBROUTINE Func(x,y) IMPLCIIT NONE DOUBLE PRECISION, INTENT(IN) :: x  !宣言部DOUBLE PRECISION, INTENT(OUT) :: y y = 4.0 * x**3 - 5.0 * x        !実行部END SUBROUTINE Func END PROGRAM EXAMPLE2サブルーチンではIMPLICIT NONEを改めて宣言(推奨)サブルーチンの引数にはINTENT属性をつけることを推奨INTENT(IN) :サブルーチンに値が受け渡され、サブルーチン内で値の変更ができない変数(入力引数) INTENT(OUT): サブルーチンで値がセットされる変数(出力引数) INTENT(INOUT): サブルーチンに値が受け渡され、サブルーチンで値を変更できる変数(入出力引数) ○再帰関数副プログラムやサブルーチンの中で自分自身(関数副プログラムやサブルーチン)を引用することを再帰という。漸化式の計算などに使える。関数副プログラムを再帰的に呼び出すためにはRECURSIVEをつける基本例(フィボナッチ数列) RECURSIVE FUNCTION Fibonacci(N) RESULT(fibo) INTEGER, INTENT(IN) :: N INTEGER :: fibo  !結果を代入する変数IF(N .LT. 0) THEN fibo = -1 RETURN END IF IF(N .EQ. 0) THEN fibo = 0 ELSE IF(N .EQ. 1) THEN fibo = 1 ELSE fibo = Fibonacci(N-1) + Fibonacci(N-2) END IF RETURN END FUNCTION Fibonacci関数の実行結果はFibonacciではなくRESULT句で指定された変数fiboに代入されるサブルーチンの場合もRECURSIVEキーワードをつければよい。 ○関数・サブルーチンでの複数の値・配列の受け渡し出力が(多次元)配列一つであれば配列型の関数としてもよいし、出力が複数配列、変数にわたる場合はサブルーチンの引数に入れる。基本例：外積を計算(関数を用いて) PROGRAM  TEST IMPLICIT NONE DOUBLE PRECISION :: a(1:3), b(1:3), c(1:3) a(1) = 6.0d0; a(2) = 3.0d0; a(3) = 4.0d0; b(1) = 3.0d0; b(2) = -2.0d0; b(3) = -4.0d0; c(1:3) = OUTERPRODUCT(a(1:3), b(1:3)) WRITE(*,*) c(1:3) CONTAINS FUNCTION OUTERPRODUCT(a, b) DOUBLE PRECISION, INTENT(IN) :: a(1:3), b(1:3) DOUBLE PRECISION :: OUTERPRODUCT(1:3) !3つの要素を持つ配列として関数を定義OUTERPRODUCT(1)=a(2)*b(3)-a(3)*b(2); OUTERPRODUCT(2)=a(3)*b(1)-a(1)*b(3); OUTERPRODUCT(3)=a(1)*b(2)-a(2)*b(1); RETURN END FUNCTION OUTERPRODUCT END PROGRAM TEST PROGRAM  TEST IMPLICIT NONE DOUBLE PRECISION :: a(1:3), b(1:3), c(1:3) a(1) = 6.0d0; a(2) = 3.0d0; a(3) = 4.0d0; b(1) = 3.0d0; b(2) = -2.0d0; b(3) = -4.0d0; CALL OUTERPRODUCT(a(1:3), b(1:3), c(1:3))  !入力も出力も引数に入れるWRITE(*,*) c(1:3) CONTAINS SUBROUTINE OUTERPRODUCT(a, b, c) DOUBLE PRECISION, INTENT(IN) :: a(1:3), b(1:3) DOUBLE PRECISION, INTENT(OUT) :: c(1:3) c(1)=a(2)*b(3)-a(3)*b(2); c(2)=a(3)*b(1)-a(1)*b(3); c(3)=a(1)*b(2)-a(2)*b(1); RETURN END SUBROUTINE OUTERPRODUCT END PROGRAM TEST
○フアイル入出力
標準入力：端末上でのキーボードからの入力READ(*,*) varなどで標準入力を変数へ読み込める。標準出力：ディスプレイ上の端末への出力WRITE(*,*) varやPRINT *, varで変数を標準出力に表示できる。標準エラー出力：ディスプレイ上への端末へ出力されるが標準出力とは区別される。 WRITE(0,*) varで変数を標準エラー出力に表示できる。 UNIX上で標準入出力をファイル入出力に変更する:リダイレクト標準出力への出力結果をファイルに保存。a.outが実行ファイルとすると> ./a.out > outputfile outputfileに./a.outのプログラム実行による標準出力への出力結果を上書き保存>>すでに存在するファイルに上書きではなく追記したい場合./a.out >> outputfile outputfileの末尾に./a.outのプログラム実行による標準出力への出力結果を追記保存2>標準エラー出力への出力結果をファイルに上書き保存。 ./a.out 2> errorfile標準出力とエラー出力を異なるファイルに上書き保存する場合は./a.out > outputfile 2> errorfile同じファイルに保存する場合は (bashの場合) ./a.out >& outputfileまたは./a.out &> outputfileなどファイルの値を標準入力にわたす場合./a.out < inputfile inputfileの内容が標準入力に渡される。 Fortranで入出力ファイルを指定する基本例（入力ファイルを装置番号1番に、出力ファイルを装置番号2番に割り当て、それぞれのファイルに入出力する） OPEN(1,FILE='inputfile',STATUS='UNKNOWN') OPEN(2,FILE='outputfile',STATUS='UNKNOWN') READ(1,*) hoge WRITE(2,*) hoge CLOSE(1) CLOSE(2)補足説明：　inputfile, outputfileには操作したいファイル名を入力するREAD, WRITE文の1つ目の変数に読み書きを行う入出力装置番号を指定する。装置番号を＊としたときは標準入出力から読み書きをするREAD(*,*)とすると入力は5番のファイル（標準入力、画面上）から読み込むWRITE(*,*)とすると出力は6番のファイル（標準出力、画面上）へ書き出すWRITE(0,*)とすると出力は0番のファイル(標準エラー出力、画面上)へ書き出すOPEN文は画面(標準入出力)以外のファイルからの入出力をする為に使う開けたら(OPEN)、閉じる(CLOSE)のを忘れずにSTATUS指定子：'OLD'：すでにファイルが存在する場合'NEW':ファイルが新しく作られる場合'REPLACE': ファイルが存在する場合は前のファイルが削除される'UNKNOWN': デフォルト値。ファイルが存在する場合も存在しない場合もある。存在しない場合は新しく作成する。 ACTION指定子：'READ'：読み込み専用でファイルを開く'WRITE'：書き込み専用でファイルを開く'READWRITE':デフォルト。読み書き可能。 POSITION指定子：  'ASIS': デフォルトの場所、通常ファイルの先頭位置'REWIND':ファイルの先頭位置'APPEND': ファイルの末尾位置存在するファイルをオープンして出力した場合上書き保存され、前の内容は削除される。すでに存在するファイルの内容を消さずに一番最後に結果を出力したい場合はOPEN(1,FILE="ファイル名", STATUS="OLD", POSITION="APPEND")などとしてファイルをオープンする。 ○書式指定（I:整数、F:実数）基本例a）5桁までの整数を表示WRITE(*,’ (I5)’) ihoge b) 全桁数15、小数点以下8桁の実数を3つ表示WRITE(*,’ (3F15.8)’) xhoge, yhoge, zhoge c) 5桁までの整数を2つ表示後、全桁数15、小数点以下8桁の実数を3つ表示WRITE(*,’ (2I5,3F15.8)’) ihoge, jhoge, xhoge, yhoge, zhoge編集記述子の種類編集記述子　形式意味
X wX空白(幅w) / /改行例WRITE(*,' (3X,I5)') 123 WRITE(*,' (F8.2)') 123.4567 WRITE(*,’ (E8.2)’) 123.4567 WRITE(*,’ (A8)’) “ABC”

○プログラムの終了(エラー処理)
STOP文でプログラムの実行を終了できる。" "で文字列をエラー出力に出せる。例： IF(n .LT. 0) STOP "n should be zero or positive"これはIF (n .LT. 0) THEN WRITE(6,*) "n should be zero or positive" STOP END IFと同じ。
○コンパイル
$ gfortranプログラムソースファイル.f90  -o実行ファイル名コンパイルオプション-O0, -O1, -O2, -O3 : 最適化才プション-ffree-line-length-none : デフオルトでは一行132文字であるがこの制限を撤廃-Wall : 全てのコンパイル時の警告メッセージを出力-Wuninitialized : 初期化されていない変数を検出-pedantic：標準外の機能利用を警告-fbounds-check：配列の領域外参照を検出-ffpe-trap=invalid,zero,overflow 浮動小数点例外発生時に異常終了-fbacktrace異常終了時にプログラムソースコードの行番号を表示○デバッグ文法以前のチェック事項①　変数の打ち間違いは無いか？ ②　配列の大きさが、定義された範囲を超えていないか？ ③　DO-END DO、IF THEN ELSE IF-ELSE-END IFなどがきちんと閉じているか？ ④　emacsでは正しくコーディングされているとタブを押したときに各行が整列する。実践的なデバッグの方法①　色々な所にWRITE(*,*) /PRINT *,文を挿入し、途中結果、DOループの変数の増え方等をモニターする。 ②　!でコメント化することでソースコードの保存や実行を飛ばすことも可能。 ③　doループの変数がちゃんと受け渡されているかどうかチェックする。特に、配列の大きさを超える変数が受け渡されると、他のデータを破壊してしまうので要注意。 ④　配列にきちんとデータが読み込まれているかチェック。 ⑤　検索コマンドで、同じ変数がちゃんと検索されるかどうかチエック。 ⑥　コンパイル時にデバッグオプションを追加