こんにちは(@t_kun_kamakiri)
本記事ではFortranの変数とデータの型について解説を行います。
実例を交えながら確認した方が理解しやすいし、何より楽しいと思うのでこちらに書いた「マンデルブロー集合」のコードを例に確認していくことにします。
マンデルブロー集合のFortranコード
全体のコードがこちら。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | program main implicit none integer, parameter :: Nmax=50, Nx=1024, Ny=1024 double precision, parameter :: Lx=4.d0, Ly=3.d0, dx=Lx/dble(Nx), dy=Ly/dble(Ny) complex(kind(0d0)), parameter :: uso=(0.d0,1.d0) integer :: i, j, n, m double precision, allocatable, dimension(:) :: x, y complex(kind(0d0)) , allocatable, dimension(:,:) ::z, c character(len=40) filename allocate( x(0:Nx-1) , y(0:Nx-1), z(0:Nx-1,0:Ny-1), c(0:Nx-1,0:Ny-1)) call system("mkdir data") m = 0 !----------------------------------------------------------------------------------- z = 0 do j=0,Ny-1 do i=0,Nx-1 x(i) = -Lx/2.d0+dx*dble(i) y(j) = -Ly/2.d0+dy*dble(j) c(i,j) = x(i) + uso*y(j) do n=0,Nmax if(cdabs(z(i,j))>2.0d0 .or. n == Nmax) exit z(i,j) = z(i,j)**2 + c(i,j) end do ! 発散しなかったCの集合(Cを上書き) if (n == Nmax) then c(i,j) = 0.0 else ! 発散したCの集合(Cを上書き) c(i,j) = dble(n) end if end do end do deallocate(z) !----------------------------------------------------------------------------------- !output of movie file write(filename,"(a,i5.5,a)") "data/julia_",int(m),".vtk" open(10,file=filename) write(10,"('# vtk DataFile Version 3.0')") write(10,"('test')") write(10,"('ASCII ')") write(10,"('DATASET STRUCTURED_GRID')") write(10,"('DIMENSIONS ',3(1x,i4))") Nx, Ny, 1 write(10,"('POINTS ',i9,' float')") Nx*Ny*1 do j=0,Ny-1 do i=0,Nx-1 write(10,"(3(f9.4,1x))") x(i), y(j), 0.d0 end do end do write(10,"('POINT_DATA ',i9)") Nx*Ny*1 !date input write(10,"('SCALARS julia float')") write(10,"('LOOKUP_TABLE default')") do j=0,Ny-1 do i=0,Nx-1 write(10,*) cdabs(c(i,j)) end do end do close(10) end program main |
こちらを実行することでマンデルブロー集合を再現できます。
美しいジュリア集合
と
マンデルブロー集合 pic.twitter.com/yoxZv8RzPe— カマキリ🐲Python頑張る昆虫 (@t_kun_kamakiri) April 11, 2022
コードはそこまで長くないのでべた書きしていますが、追々改良を進めていきます。
変数・データの型
Fortranの変数とデータの型の定義は以下の部分です。
1 2 3 4 5 6 7 | integer, parameter :: Nmax=50, Nx=1024, Ny=1024 double precision, parameter :: Lx=4.d0, Ly=3.d0, dx=Lx/dble(Nx), dy=Ly/dble(Ny) complex(kind(0d0)), parameter :: uso=(0.d0,1.d0) integer :: i, j, n, m double precision, allocatable, dimension(:) :: x, y complex(kind(0d0)) , allocatable, dimension(:,:) ::z, c character(len=40) filename |
変数とデータの型は以下のように定義します。
1 | データの型:変数 |
データの型には以下のような組み込み型があります。
整数型 | 4バイト整数(符号付き) | integer |
実数型 | 単精度 倍精度 | real double precision |
複素数型 | 単精度 倍精度 | complex complex(kind(0d0)) |
論理型 | logical | |
文字型 | character |
変数の属性
変数に属性を付けることができます。
parameter属性
例えば以下のように変数が定数であることを明示して値がプログラム内で固定することができます。
1 | integer, parameter :: Nmax=50, Nx=1024, Ny=1024 |
dimension
例えば以下のように変数配列の大きさを指定することができます
1 | double precision, dimension(Nx, Ny):: x, y |
これは以下のように書いても良いのですが、上記の書き方の方がシンプルでわかりやすい書き方になっていますね。
1 | double precision :: x(0:Nx-1), y(0:Ny-1) |
allocatable属性
配列の割付けにはallocatable属性を使って配列を定義することができます。しかし、2行目では配列の大きさは決まっていないので4行目のallocate文で配列の大きさを定義する必要があります。
1 2 3 4 5 6 | ! 割付け配列を宣言 double precision, allocatable:: x(:), y(:) ! 配列の割付け allocate( x(0:Nx-1) , y(0:Nx-1)) ! 配列の解除 deallocate(x, y) |
このように配列を定義して、不要になった変数はdeallocate文で配列の解除を行うとに対してはメモリ削減に良いです。
本プログラム内ではこれらを組み合わせて以下のように書いています。
1 | double precision, allocatable, dimension(:) :: x, y |
参考書
Fortranは日本の書籍がかなり少ないのですが以下のようなサイトがあり、とても参考になります。
その他出版されている参考書を挙げておきます。
こちらの参考書は文法からちょっとした応用(偏微分方程式を解く)まで解説がありFortranを使う人にとって手元に置いておきたい参考書ですね。OpenMPによる並列計算の解説もあります。
しかし、Fortran90/95の記述のみなのでForran2003以降を学ぶにはやはり上記のサイトを参考にした方が良いでしょう。
こちらはFortranのコード集となっています。
Fortranは科学計算のためのプログラミング言語ですので数値計算の参考コードがいっぱい載っているこちらの参考書はとても勉強になります。
Fortran文法の解説はありませんが、数値計算の勉強にはとても良いです。
こちらはC言語とFortranの両方を学びながら数計算の基礎力を身に付けるための参考書です。問題演習の全てにサンプルコードがあるため本書を読みながらサンプルコードをじっくり眺めるだけでも大変力が付きます。