コーディングにおいてよくある間違いをまとめる.
計算の優先順位は +- < */ < ** である.
print*,-1**0
これは-(1**0)と解釈されるので,出力結果は−1. -1に対してべき乗する場合は,(-1)**0.
論理演算子の優先順位は .eqv., .neqv. < .or. < .and. < .not. である.
logical :: a=.false. num :: i=1 if(a.eqv..false..or.i==1) then print*,'if' else print*,'else' end if
これは,a.eqv.(.false..or.i==1) と解釈される. (.false..or.i==1) はtrueなので,上のコードはelseを吐き出す. 前後の条件をorでつなぐ場合は, if((a.eqv..false.).or.(i==1)) としてカッコで順序を明示する.
ちなみに
になる.
すでにallocateしたかどうかわからない時は,allocatedで確かめてからallocateする. https://gcc.gnu.org/onlinedocs/gcc-4.1.0/gfortran/ALLOCATED.html
if (allocated(x).eqv..false.) allocate(x(n))
入れ子のループで,cycleやexitを使って外側に飛びたいときは,do ループにラベルをつける. これで文番号を付けずに好きなところへ飛べる.
例
outer : do i=1,n do j=1,n if(...) cycle outer end do end do outer
読み込み専用で開く場合.
open(10,file='input.dat',action='read')
その他,action='write', action='readwrite'もある.
compiler | gfortran | ifort |
---|---|---|
エラーの検出 | -Wall | -check all |
配列外参照 | -fbounds-check | -CB |
暗黙の型宣言 | -fimplicit-none | -warn declarations |
浮動小数点演算例外の検出 | -ffpe-trap=zero | -fpe0 |
標準外機能の警告 | -std=f95 | -std |
例えば以下のようにする.
gfortran filename.f90 -O2 -stand f03 -assume realloc_lhs -check all -traceback -warn all -fstack-protector -assume protect_parens -implicitnone
ファイル名をcharacter変数に代入して使う。ファイル名の変更にはwrite文を使う。 逐次計算に使える。
character(len=12) filename ... do i=1,100 ... write(filename,'(a,i4.4,a)') 'hoge',i,'.dat' open(10,file=filename) ... write(10,*) ... ... close(10) end do
処理はmovie参照のこと.
以下の記事は古い.別のページを参照せよ.
moduleファイルを含む場合,依存関係をはっきりさせる必要がある. 依存関係を変えるたびにmakeファイルを書き変えるのは面倒なので,依存関係を見てくれる f90_mod_deps.py を使う.
http://lagrange.mechse.illinois.edu/mwest/f90_mod_deps/
コンパイル不要のpardisoやompのモジュールを読み込んだり,同一ファイル内に複数のモジュールが存在し循環参照が起きる場合は,f90_mod_deps.py のwrite_depsに以下のように修正.
def write_deps(outf, filename, deps, mods): filebase, fileext = os.path.splitext(filename) #>>> loadmod="MKL_PARDISO.mod" if loadmod in deps: deps.remove(loadmod) loadmod="omp_lib.mod" if loadmod in deps: deps.remove(loadmod) #<<< outf.write("%s.o: %s\n" % (filebase, " ".join(deps))) for mod in mods: #>>> if mod in deps: deps.remove(mod) #<<< outf.write("%s: %s\n" % (mod, " ".join(deps)))
以下,Makefile のサンプル.
TARGET = a.out DEPS=hoge.deps OBJECTS = piyo.o foo.o bar.o main.o F90 = gfortran FFLAGS=-Wall -ffpe-trap=invalid,zero,overflow,underflow -fbounds-check -fimplicit-none -fbacktrace -fopenmp #FFLAGS=-O3 -fopenmp #F90 = ifort #FFLAGS=-check all -warn all -std -gen_interfaces -fpe0 -ftrapuv -traceback #FFLAGS = -mkl -O3 SOURCES=$(OBJECTS:.o=.f90) .SUFFIXES : .SUFFIXES : .o .f90 .f .f.o: ${F90} -c $< ${FFLAGS} .f90.o: ${F90} -c $< ${FFLAGS} .PHONY:all all: ${DEPS} ${TARGET} ${DEPS}: ${SOURCES} python f90_mod_deps.py --output $@ $^ ${TARGET} : ${OBJECTS} ${F90} -o $@ $^ ${FFLAGS} -include ${DEPS} %.o %.mod: %.f90 ${F90} -c $< ${FFLAGS} touch $(patsubst %.f90,%.mod,$<) clean : rm ${TARGET} *.mod *.f90~ ${OBJECTS}
複数のファイル(サブルーチンetc.)で構成されるプログラムを動かすのに便利. 以下の文を「makefile」という名前で作り,コンパイルしたいファイルと同じディレクトリに置く. (以下,main.f90, modules.f90[モジュールファイル], sub1.f90, sub2.f90をコンパイルする場合)
TARGET = a.out OBJECTS = modules.o main.o sub1.o sub2.o F90 = ifort FLAGS = -check all -warn declarations -CB -fpe0 -traceback COMMON_MOD = modules.f90 .SUFFIXES : .SUFFIXES : .o .f90 .f90.o: ${F90} -c $< ${FFLAGS} ${TARGET} : ${OBJECTS} ${F90} -o $@ ${OBJECTS} clean : rm *.o ${TARGET} *.mod ${OBJECTS} : ${COMMON_MOD}
あとは,makeコマンドを打てばコンパイル完了.そして実行(上の例では./a.outを打てば良い).
$ make $./a.out
また,以下の様にmake cleanで実行ファイル(a.out)及びオブジェクトファイル(*.o)を消去できる.
$ make clean
以下,makefileの変数について簡単に説明する.
TARGET = 実行ファイル名 OBJECTS = モジュールファイル プログラムファイル (すべて拡張子は.oとする.) F90 = コンパイラコマンド (gfortranを使うなら「gfortran」) FLAGS = コンパイラオプション COMMON_MOD = モジュールファイル (拡張子は.f90)
データファイルの中に何行あるか分からないときにはiostatかendを使う. iostatの方がスマートなやり方かも.
read文にiostatのオプションを付ける. iostatが正の数を返す場合はエラー,負の値を返す場合は行の終わりを意味するらしい.
program hoge implicit none real a,b integer i,inputstatus do i=1,10 read(*,*,iostat=inputstatus) a,b if(inputstatus>0) stop "error" if(inputstatus<0) exit write(*,*) a,b,a**2-b end do end program hoge
endを使う.
以下サンプル.プログラムの中では10回ループを回すが,読み込むのは5行分だけ.
gfortran hoge.f90 ./a.out < hoge.dat
hoge.f90
program hoge do i=1,10 read(*,*,end=999) a,b write(*,*) a**2-b end do 999 continue end program hoge
hoge.dat
1. 1. 2. 4. 3. 9. 4. 16. 5. 25.
浮動小数点演算例外を検出するコンパイラオプションがあるので、それを使用する。
保存するためのmakefile
DATE= `date +%y%m%d%H%M` TAR = backup/backup${DATE}.tgz backup : tar czvf ${TAR} Makefile *.f90
宣言文で宣言した変数以外を利用しないようにする。 長いプログラムを書く場合はミスを避けるためにも使用するべき。 自由形式の場合はuse文の後に使用。
program hoge use hoge_lib implicit none real(8) a,b,c, ...
write(?,*)やread(?,*)の?に入る番号。 通常、5が標準入力(キーボード)、6が標準出力(ディスプレイ上の端末)に使用されるので、 5と6を使ってopenするのは避けるべき。 slatecのI1MACHを使えば、標準入力、標準出力の番号が調べられる。 装置番号にはcharacterも入る。
ファイル名をcharacter変数に代入して使う。ファイル名の変更にはwrite文を使う。 逐次計算に使える。
character(len=12) filename ... do i=1,100 write(filename,'(a,i4.4,a)') 'hoge',i,'.dat' open(10,file=filename) ... write(10,*) ... ... close(10) end do
連続してプログラムを実行したいとき、shファイルが便利。 端末で入力する内容をあらかじめファイルに書いておき、それを実行すれば、上から順に実行してくれる。 windowsで言うバッチファイル。
gfortran hoge.f90 cd case10 ../a.out cd ../case20 ../a.out cd ../case30 ../a.out
$ sh hoge.sh