1
0

Fortran備忘録(1) Fortran 90/95の超基本メモ

Posted at

プログラミング苦手な上に、Fortran太古の言語とか言われてるけど、研究で必要なので備忘録。。。
これだけ覚えれば、あとは実際のコード見ながらでもなんとか読めるでしょうという程度まで。
簡単な順に書いているわけではないので、初心者は2周読めば理解できるかも。
コーディングする際は別記事Fortran備忘録(2) 用途別Fortran90/95基本メモ参照。

環境構築とコンパイル

Macなのでコンパイラのgfortranが内包されたgccをHomebrew環境下でインストール

brew install gcc #インストール
which gfortran   #gfortranのパス確認
gfortran -v      #バージョン確認
hello.f90
program hello
	print *, 'Hello, world!'
end program hello
gfortran hello.f90 -o hello.out
./hello.out

テキストファイルへの出力リダイレクトを行う場合、

gfortran hello.f90 -o hello.out
./hello.out > output.txt
Hello, world!

モジュールなどの副プログラムを使用しているコードを実行する場合、

gfortran mod_params.F90 mod_one.F90 mod_two.F90 main.F90 -o main.out

とするか、あるいは、以下のようにオブジェクトファイルを作る。

gfortran -c mod_params.F90
gfortran -c mod_one.F90
gfortran -c mod_two.F90
gfortran -c main.F90
gfortran mod_one.o mod_two.o main.o -o main.out

※よく使うgfortranのデバッグオプション

オプション 意味
-c オブジェクトファイルの生成
-O2 main.F90の直後に置いて)最適化
-fbounds-check 配列の領域外からの参照を検出

ルール

  • Fortran90/95であることを明らかにするため、.fより.f90を使うのが慣例。(自由形式のFortran90/95コードでも.f90がよく使われるっぽい(?)プリプロセッサを使う際は.F90と大文字にする!(用途別Fortran90/95基本メモ参照))
  • 必ず宣言部→実行部→副プログラム部の順で書く。(実行部の中で宣言できない。)
  • プログラムはendで終える。
  • program文は省略可能。
  • コメントアウトは!(行頭、行末)、またはFortran77のみ(?)行頭にc。コメント内日本語ok。
  • 大文字小文字の区別が無いので、SUBROUTINEとかCONTAINSとか、区切りを大文字にしておくと見やすい。
  • プログラム名と同じ変数名は良くない。
  • f95の自由形式に対応しているコンパイラがほとんどなので一行の文字数問題は気にしなくていい。(132文字まで)規定文字数を超えると書いてあっても無視される。
  • 一行を分ける時は一行目の最後に&。(文字列中で改行もでき、その時は一行目末に加え、二行目の最初にもスペース入れずに&を入れる。)
  • **implicit noneを必ず宣言する。**外すと暗黙の型規約が適用され、i~nが整数、他が実数になるらしい。

制御構造(と簡単なサンプルコード)

反復のdoループ

	do i = 1, 100
		sum = sum + i
	enddo
全体

do_loop.f90
PROGRAM do_loop
	implicit none
	integer :: i, sum
	sum = 0

	do i = 1, 100				!
		sum = sum + i			!
	enddo						!

	write(*, *) 'sum = ', sum
END PROGRAM do_loop

後判定のdo while構文もある。

条件分岐のif

    if (i == 0) then
        write(*,*) i, "は0です。"
    else if (i < 0) then
        write(*,*) i, "は負です。"
    else if (mod(i,2) == 0) then
        write(*,*) i, "は偶数です。"
    else
        write(*,*) i, "は奇数です。"
    end if
全体

if_oddeven.F90
PROGRAM if_oddeven
    implicit none

    integer :: i
    print *, "整数を入力:"
    read(*,*) i

    if (i == 0) then
        write(*,*) i, "は0です。"
    else if (i < 0) then
        write(*,*) i, "は負です。"
    else if (mod(i,2) == 0) then
        write(*,*) i, "は偶数です。"
    else
        write(*,*) i, "は奇数です。"
    end if

END PROGRAM if_oddeven

then必須。
ケース分岐のselect構文もある。

※比較演算子の別表記
どっちも使える。

意味 よくあるやつ ドットと文字
Equal x == y x .eq. y
Not Equal x /= y x .ne. y
Greater Than x > y x .gt. y
Greater than or Equal x >= y 'x .ge. y`
Less Than x < y x .lt. y
Less than or Equal x <= y x .le. y

not equalは!=じゃなくて、/=なことに注意!

論理演算子
[否定] .not.を使う。
[かつ、または] Fortranに&&||はない!.and..or.を使う。
[論理値の比較].eqv.``.neqvもある。

##宣言と型

  • 数値型
    • 整数型
      • 基本整数型integer
    • 実数型real(8)
    • 複素数型
  • 文字型
  • 論理型logical
    • 論理定数.true.あるいは.false.を持つ。(が、表示される時はTF。)

宣言

implicit none

real(8) :: real_variable  
real(8), parameter :: pi  = 3.14159265359d0
real(8), allocatable :: real_number_data(:)

::はあるに越したことはないっぽい。
allocatable

parameter

allocate(real_number_data(number_of_data))

save属性の局所変数は複数回の副プログラム呼び出しに対して値を保持する。
(saveが付いていなくてもFortranでは初期化(宣言と代入が同一文で行われる)時に自動的にsave属性が付く)(厄介)

SUBROUTINE glob
	integer, save :: global_variable = 5
END SUBROUTINE glob

入出力

標準入出力(ディスプレイへの入出力)

!入力
read(*,*) x, y, z
!出力
print *, 'sum =', sum, 'dayo!'
write(*,*) 'sum =', sum, 'dayo!'

入力はreadを使えば、ターミナルで変数の入力を求められるようになる。(print *, 'x=?'などとしておく。)
出力は普通printwriteを用いる。
read(*,*)write(*,*)*は出力先、書式を決める装置番号や編集記述子(printの*も)というものだが、どちらも標準として(*,*)
printは後ろにカンマがいる。
出力するものは、sumなどの変数でも'sum = 'などの文字列でもok。

ファイル入出力と開閉

##関数、サブルーチン、モジュールの違いと使い方
関数は返り値がある。
サブルーチンは返り値がない。(他言語でいうvoid型関数。)
モジュールはサブルーチンや関数をまとめたもの。

関数(function)

後述するサブルーチンとは違って、使用時CALLする必要はない。

仮引数には以下のintent属性を付けることが必須。(ローカル変数には不要。)

属性 実引数からの値の受け取り 値の演算・代入と保持
intent(in) ×
intent(out) ×
intent(inout)

要は、関数・サブルーチンを使うときに引数に入れる値が決まっている場合はintent(in)
関数・サブルーチン中で仮引数の値が代入される場合はintent(out)

サブルーチン(subroutine)

個人的に「手続」っていうイメージ。
他言語でいうvoid型関数。
使用時はCALL name_of_subroutine(arg)で呼び出す。
主プログラム内でCALLの行に辿り着くと、副プログラムの一行目から最後まで演算が行われ、主プログラムの次の行に移る。副プログラムの演算を途中で抜け出したい時はreturn
冒頭でサブルーチンには返り値がないと言っているが、intent(out)を用いて値を計算・代入することは可能であり、実際二つ以上の値を返したい場合はサブルーチンが用いられる。

モジュール(module)

使う時はUSE name_of_moduleで呼び出す。
USE宣言はimplicit noneより前。
モジュール内のサブルーチンを呼び出す時は、USE宣言した後にCALL name_of_subroutine(arg)
Fortranでグローバル変数を用いる際はsaveなどもあるが、一般にmod_params.F90などのモジュールを作り、その中に宣言するのが通例。

プログラム単位と副プログラムについて

ファイル分割が許される最小単位

  • 主プログラム(program 〜 end program )
  • 外部副プログラム(containされない関数、サブルーチン)
  • モジュール
  • block data

の4種類。以下で一つずつ説明。
副プログラムとは、関数あるいはサブルーチンのこと。
以下のように、副プログラムは内部副プログラム、外部副プログラム、モジュール副プログラムの3種類。

主プログラム(main program)

内部副プログラムは主プログラム内に含まれる(containされる)関数、サブルーチン。主プログラム内でしか使えないから、機能拡張に向かない。外部副プログラムでいい。

PROGRAM name_of_program
	!宣言部
	!実行部
CONTAINS
	!内部副プログラム(internal subprogram)1
	!内部副プログラム(internal subprogram)2
	!...
END PROGRAM name_of_program

外部副プログラム(external subprogram)

反対に、主プログラム内に含まれない(containされない)関数、サブルーチン。

FUNCTION name_of_function(arg)
	!宣言部
	!実行部
CONTAINS
	!内部副プログラム
END FUNCTION name_of_function
SUBROUTINE name_of_subroutine(arg)
	!宣言部
	!実行部
CONTAINS
	!内部副プログラム
END SUBROUTINE name_of_subroutine

モジュール(module)

MODULE NAME_OF_MODULE
	!...
CONTAINS
	!モジュール副プログラム(この中にさらに内部副プログラムを入れることは可能。)
END MODULE NAME_OF_MODULE

block data

宣言部だけでファイルを作るという今はほぼ使われない化石。(コンセプトは好きだけど。。共通ブロックに問題があって良くない(?))
今はパラメータを集めたモジュールを作ればいい。
nag Fortran 入門: 知識として必要な過去の Fortranが詳しい。
(Fortranは古くから存在するプログラミング言語の中では比較的数式を簡単に表現できるのもあって、アカデミックな、特に地球科学分野などで伝統的に使われていることが多く、時にはFORTRAN77のような読みづらいものが残っていることもある。このページは他にもそのような色んな過去の産物(GO TOとか文番号とか)のことが書いてあって、Fortran95からより古いバージョンを追っていくにあたり非常に助かった。)


※このように、基本色んなプログラム単位の中に内部副プログラムを置くことができるが、内部副の中に内部副とする事だけは不可(内部副プログラムは入れ子構造禁止)

参考

nag Fortran入門
恐らくインターネット上ではFortran入門として一番見られているサイト。ありがとうありがとう

Fortran 入門: 知識として必要な過去の Fortran
色んな過去の産物のことが書いてあって、Fortran95からより古いバージョンを追っていくにあたって非常に助かった。

数値計算のためのFortran90/95プログラミング入門
有名な書籍(amazon)。最近(2020)第2版が出たみたいなので。。

Fortran演習
とてもわかりやすい。
東京大学理学部地球惑星物理学科の地球惑星物理学演習の授業で作られたみたい。さすが東大

個人的メモ

覚えながら、忘れそうなところを、合間時間を使って書いていく。
コードを読んでてわからなかったところを書く。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0