Fortran Tips

Fortranを勉強し始めて大事だと思ったことまとめ

目次

ファイル読み取り

readfile.f

c c Sample program for using input.dat file c ver. 1.0 made by R. Saito 2020.5.12 c open(50,file='input.dat',status='old') c read(50,20) n,m read(50,30) Ef read(50,40) filenumber c write(*,*) '(',n,m,') will be calculated' write(*,*) 'for the Fermi energy', Ef, 'eV' write(*,*) 'filenumber =', filenumber c close(50,status='keep') c 20 format(2I4) 30 format(f15.5) 40 format(f15.5) c stop end

input.dat

6 4 1.2 100

実行結果

maeda@flex:~/for/sample/input_file$ gfortran readfile.f maeda@flex:~/for/sample/input_file$ ./a.out ( 6 4 ) will be calculated for the Fermi energy 1.20000005 eV filenumber = 1.00000005E-03

mainとsubroutinでのメモリ空間の共有(Cでいうポインタ渡しのようなもの)

common /ラベル/var1,var2
comonnの書き方ラベル(ブロック)を指定し,そのブロック内の変数を同じラベルで書かれたcommon文で指定された変数とメモリ空間を共有する

common.f

c c common check 2020.5.29 R, Saito c implicit real*8(a-h,o-y) implicit complex*16(z) common /bl1/ kx(100),ky call kxky write(*,*) 'kx,ky=',kx(32),ky stop end c subroutine kxky implicit real*8(a-h,o-y) implicit complex*16(z) common /bl1/ kx(100),ky kx(32)=1 ky=2 return end c

実行結果

maeda@flex:~/for/sample/common$ gfortran common.f maeda@flex:~/for/sample/common$ ./a.out kx,ky= 1 2

common.fを例にとってみると,
subroution kxky の/bl1/ kx(100),kyは別に全く同じじゃなくてもいい

common2.f

c c common check 2020.5.29 R, Saito c implicit real*8(a-h,o-y) implicit complex*16(z) common /bl1/ kx(100),ky call kxky write(*,*) 'kx,ky=',kx(32),ky stop end c subroutine kxky implicit real*8(a-h,o-y) implicit complex*16(z) common /bl1/ a(100),b a(32)=1 b=2 return end c

実行結果

maeda@flex:~/for/sample/common$ gfortran common2.f maeda@flex:~/for/sample/common$ ./a.out kx,ky= 1 0

ただ,混乱を招く場合があるため同じにしておいたほうが安全
どうせ同じにするならコピペミスをへらすためにもヘッダーをとして定義してインクルードするとよい
下の例(common3.f)ではついでにimplicitもヘッダーに入れた

common3.f

c c common check 2020.5.29 R, Saito c c include "header3.f" call kxky write(*,*) 'kx,ky=',rkx(32,32),rky(1,1) stop end c subroutine kxky include "header3.f" rkx(32,32)=1 rky(1,1)=2 return end c

header3.f

implicit real*8(a-h,o-y) implicit complex*16(z) parameter(ikx=100,iky=200) c /cnt/ no hensuuha call init de teigi common /cnt/ n,m c /kx,ky/ ha call kxky de teigi common /bl1/ rkx(ikx,iky),rky(ikx,iky)

実行結果

maeda@flex:~/for/sample/common$ gfortran common3.f maeda@flex:~/for/sample/common$ ./a.out kx,ky= 1.0000000000000000 2.0000000000000000

common文について補足

common文では1つのラベルで確保できるサイズが決まっており,それを超えるとコンパイルエラーを吐くため
あるサブルーチン間同士で共有するからといって1つのラベルで共有したい変数すべてを共有できるわけじゃない
参考1
参考2

複数のファイルにまたがるプログラム

プログラムが大規模化すと管理が面倒になったりソースコードを追うのが面倒になる
プログラムで使われる関数やサブルーチンを別ファイルにまとめるとソースコード全体の見通しが良くなる

メインのプログラム(sample_main.f90)

program sample_main include "sample_init.f90" call cal_kx print *,"main program output" do j = j_min, j_max do u = 1, n_large print * , rkx(j,u) end do end do end program sample_main

サブルーチンのプログラム(sample_sub.f90)

subroutine cal_kx include "sample_init.f90" print * , "called cal_kx" do j = j_min, j_max do u = 1, n_large rkx(j,u)=j*n_large+u end do end do end subroutine

2つのプログラムのヘッダー(橋渡しのようなもの)(sample_init.f90)

implicit double precision(a-h,o-r,t-y) implicit integer(i-n) ! i,j,k,l,m,n から始まる変数はすべてint型 implicit complex(kind(0d0))(z) ! zから始まる変数はすべて複素数 implicit character(len=2)(s) ! stringの頭をとったcはconstなどで使いそうだったやめた ! implicit double precisiond imension(10,10)(m) parameter(j_min=0,j_max=2,n_large=3) common /array/ rkx common /cnt/n,m real rkx(j_max,n_large)

実行結果ヘッダーは一緒にコンパイルしない!!!

maeda@tube63:/abinitio/maeda/fortran/iwasaki/CDparallel/CDpara_ref$ ifor sample_main.f90 sample_sub.f90 maeda@tube63:/abinitio/maeda/fortran/iwasaki/CDparallel/CDpara_ref$ ./a.out called cal_kx main program output 1.000000 7.000000 8.000000 4.000000 5.000000 6.000000 7.000000 8.000000