Fortranチートシート
自分は普段Fortranを主に使っているのですが、チートシートらしいチートシートを作ってこなかったために毎回過去のコードを解読してコードの流れを思い出したり、GPT先輩に組み込み関数の仕組みを聞いたりしています。しかし、Fortanユーザーとして、これは褒められたものではありません。Fortranという最古の高級言語を使う以上、気品あるプログラマーとして、自分で作ったチートシートを参照するべきではないでしょうか。だって、Fortranは紳士のプログラミング言語だからね!
というわけで、以下がそのチートシートになります。(随時編集するつもりです。)
入出力
program main
implicit none
integer::io,filesize,i
real(8),allocatable::data_in(:)
!=============file読み込み================
open(10,file='../datafile/input.dat',status='old',action='read')
!ファイルサイズを取得する
filesize=0
read(10,'(A)')
do
read(10,'(A)',iostat=io)
if(is_iostat_end(io)) then
exit
end if
filesize=filesize+1
end do
!filesizeを取得したら、data_inにallocateして、読み込みを開始する。
allocate(data_in(filesize))
rewind(10)
read(10,'(A)')
do i = 1,filesize
read(10,*) data_in(i)
end do
close(10)
!========================================
end program
とにかくめんどくさい。まず一回、ファイルの終わりに到達したかどうかチェックしながらdoループを回すことで、filesizeを取得する。そしたら、データの入れ先の配列をfilesizeにallocateして、もう一度doループを回しながらデータを読み込んでいく。めんどくさい!
module関係
基本構文
module test_module
implicit none
integer,parameter::n
real(8) :: x
contains
subroutine hoge()
implicit none
write(*,*) 'hello world'
end subroutine
end module test_module
program main
use test_module
implicit none
write(*,*) i !>>3
x=1
write(*,*) x !>>1
call hoge() !>>hello world
end program
moduleで出来ることは、変数の宣言と、subroutineや関数の定義。main program内でuse test_moduleすると、それら変数・subroutine等が使える様になる。以下のようなプログラムはNG。
module hoge
implicit none
write(*,*) 'hello world'
end module hoge
write(*,*) 'hello world'は変数の宣言でもsubroutine系統でもないので、こんなことはできない。また、moduleのみのファイルをコンパイルすることはできず、必ず以下の様にprogram mainを下につけるか
module hoge
implicit none
!hogehoge
end module
program main
implicit none
end program
コンパイルの際に
> gfortran module_only.f90 program.f90
の様に、moduleのファイルとprogramのファイルを同時にコンパイルする必要がある。
また、moduleを含むファイルを走らせると、.modファイルが生成される。同一ディレクトリにある.modファイルは、program内部でuse moduleすることができる。すなわち、
-file
|-module.mod
|-main.f90
の様になっていれば、main.f90の内部でmoduleを定義することなく、
program main
use module
implicit none
end program
の様にすることができる。大規模プロジェクトとかなら、個別にmoduleファイルを書いて、最後にprogramでまとめてコンパイル、なんてことができたりもする。ただまあ、ファイルを分けると非常にみづらいので、
module module1
end module1
module module2
end module2
.
.
.
program
end program main
としてしまうのが楽な気がする。よっぽど普遍的な関数とかでもなければ。
変数のスコープについて
moduleで定義した変数のスコープはsubroutineを貫通する。すなわち、
module hoge
implicit none
integer :: n
end module hoge
program main
use hoge
implicit none
stop
contains
subroutine hogehoge()
implicit none
n=n+1 !<<<このnはmodule hogeで定義したn!
end subroutine
end program
module hoge
implicit none
integer :: n
end module hoge
module hogehoge
use hoge
implicit none
contains
subroutine foo
implicit none
n=n+1 !<<<このnもmodule hogeで定義したn!
end subroutine
end module hogehoge
すなわち、use module hogeしたなら、そこがprogramであれmoduleであれcontainされるsubroutineにおいてhogeの変数はグローバルとなる。
※program で変数nを定義しても、同program内でcontainされるsubroutineにnは貫通しないのとは対称的。