リンク コンパイラー(フリーウェア) 超入門編

(工事中)
学部の 3 年生の必修の授業でならった言語が Fortran で,それ以来お世話になってます。最近は
大抵のことは Matlab/Octave/R で済ませますが,計算速度の必要な計算はやはり Fortran です。とい
うわけで,説明用の資料として。
リンク
・Fortran90/95 入門 高木先生@東京大学
・Fortran90 プログラミング 富田先生@京都大学
・データ解析のための Fortran90/95 入門 愛媛大学農学部(気象系)
・Fortran 標準コーディングルール 気象研究所 気象関係者間でのソースコードの流通を目
的としたコーディングルール
コンパイラー(フリーウェア)
・GNU Fortran gfortran
・The G95 Project g95
・Intel Fortran Compiler Intel Fortran (ifort) 非商用版
超入門編
最初の一歩
プログラム・ファイルの名前(拡張子)の付け方
・ fortran90/95 規格のソース sample.f90
・ fortran77 規格のソース sample.f
プログラムのコンパイル
・gfortran sample.f90 -o sample
・g95 sample.f90 -o sample
・ifc sample.f90 -o sample
とりあえずひな形
program sample ! プログラム文(プログラム名を宣言)
implicit none ! 使用する全ての変数の型宣言をするという宣言
integer i, j ! 整数を宣言
real(8) x
! 実数(倍精度)を宣言
...
...
end program sample ! end 文
・プラグラム文は省略可能であるが,end 文は必須。プログラム文を省略した場合には単に
end のみ。
・real(8) は,実数を倍精度(約 15 桁)の変数にするという宣言。例えば,Excel 等では標準
でこの程度の精度で演算をしているので,メモリを節約したい時以外にはあえて基本形
real(約 7 桁)を使わなくても良い。
繰り返し (do loop)
1
・ do ∼ enddo の中の処理を i の値を1から 10 まで変えながら繰り返す。
program sum
implicit none
integer i
real(8) sum, x(10) ! 実数変数 sum と実数配列変数 x(要素数が 10)を宣言
do i=1,10
x(i)=0.5*i ! 配列変数に値を設定する x(1)=0.5, x(2)=1.0, ..., x(10)=5.0
enddo
sum=0
do i=1,10
sum=sum+x(i) ! 合計 x(1)+x(2)+...+x(10) を計算する
enddo
write(*,*) 'sum= ',sum
end program sum
・ fortran77 では行番号を使い繰り返しの範囲を示すが,fortran90/95 では行番号を使用しな
い。
10
do 10 i=1,10
x(i) = 0.5*i
・ do~enddo 文で増分値を1ではなく 2 とする場合 (i=1,3,5,7,9 となる )
do i=1,2,10
x(i)=0.5*i
enddo
・ 無限ループ (抜けるための対策が必要: if, exit, stop, goto 文)
do
x(i)=0.5*i
enddo
条件分岐(if 文)
・ 配列変数 m の値が2よりも小さい場合に,配列の順位と値を表示する
program sample1
implicit none
integer :: m(5)=(/-1, 5, 3, -4, 2/) ,i
do i=1,5
if (m(i)<2) then
write(*,*) ' m<2', i, m(i)
endif
enddo
end program sample1
! m(1)=-1, ..., m(5)=2 を初期値として設定
・if 文の基本的な構造
if ( 論理式1 ) then
実行文 A (論理式1が真であれば実行文 A を実行する)
else if ( 論理式2 ) then
実行文 B (論理式2が真であれば実行文 B を実行する)
else
実行文 C (論理式1,2が真でない場合に実行文 C を実行する)
endif
・論理式の構造
if (a==b)
a と b が等しければ真
2
if
if
if
if
if
(a>b)
(a>=b)
(a<b)
(a<=b)
(a/=b)
a が b より大きければ真
a が b 以上であれば真
a が b よりも小さければ真
a が b 以下であれば真
a と b が等しくなければ真
中級編
配列変数の演算 (Fortran90/95 の魅力の一つ )
!
!
!
do i=1,10
x(i)= y(i)*5+1
enddo
x(1:10)=y(1:10)*5+1
副プログラム(サブルーチン)
program main
implicit none
integer i,num
real(8) sum
...
call sub1(num,sum)
...
end program main
subroutine sub1(num,sum)
implicit none
integer i,num
real(8) sum
...
end subroutine sub1
モジュール
fortran90 以降で出てきた新しい規格
(工事中)
上級編 gfortran + Open MP 並列化
gfortran はデフォルトで並列化に対応していました!
Fortran プログラマのための OpenMP 入門 京都大学学術メディアセンター
OpenMP 入門
■サンプルプログラム
program testOMP2
!$ use omp_lib
implicit none
print *, 'START'
!$omp parallel
print *, 'Hello! N =', omp_get_num_threads(), ' and I am ', omp_get_thread_num()
!$omp end parallel
print *, 'END'
end program testOMP2
■コンパイル % gfortran -fopenmp testomp2.f90
3
■結果 4コアの場合
start
Hello!
Hello!
Hello!
Hello!
END
N=
N=
N=
N=
4
4
4
4
and
and
and
and
I
I
I
I
am
am
am
am
0
1
2
3
ifortran + Open MP
インテル Fortran コンパイラー OpenMP 活用ガイド
■コンパイル
ifort -openmp -openmp-report2 test_omp.f90
FFTW3 を使う
1.FFTW3 をダウンロード
2. コンパイル
1. ./configure
2. make
3. make install
3.fftw3 を使用するソースをコンパイルする
% gfortran tfftw3.f90 -I/usr/local/include -L/usr/local/lib -lfftw3
ubuntu のリポジトリの libfftw3 や libfftw3-dev を使用する場合
% gfortran tfftw3.f90 -I/usr/include -lfftw3 -o tfftw3
( ライブラリやインクルードファイルのディレクトリが異なる )
・計算例
sample program
program fftw3_test
implicit none
! array size
integer, parameter :: N=16
! input data
real(8), dimension(N) ::in,in2
! output data
complex*16, dimension(N/2+1) :: out
! plan
integer(8) ::plan
integer
::i,M
include 'fftw3.f'
!=========================
! set data
!=========================
in(1)=5.0
in(2)=32.0
in(3)=38.0
in(4)=-33.0
in(5)=-19.0
in(6)= -10
in(7)= 1.0
in(8)= -8.0
in(9)= -20.0
in(10)= 10.0
in(11)= -1.0
in(12)= 4.0
4
in(13)= 11.0
in(14)= -1.0
in(15)= -7.0
in(16)= -2.0
in2(1:N)=in(1:N)
!=====================
call dfftw_plan_dft_r2c_1d(plan,N,in,out,FFTW_ESTIMATE)
call dfftw_execute_dft_r2c(plan,in,out)
call dfftw_destroy_plan(plan)
!=====================
M=N/2+1
do i=1,M
print *,real(out(i)),aimag(out(i))
end do
!
!=====================
call dfftw_plan_dft_c2r_1d(plan,N,out,in,FFTW_ESTIMATE)
call dfftw_execute_dft_c2r(plan,out,in)
call dfftw_destroy_plan(plan)
!=====================
do i=1,N
print *, in(i)/dble(N),in2(i)
end do
end program fftw3_test
入力が実数の場合の FFT 演算では、出力のメモリサイズは N/2+1 とする。半分は出力されない。
演算結果は通常の FFT 演算(Octave 等)と同じ。また、逆変換でもメモリサイズの関係はかわら
ない。
演算結果
murakami@murakami-VB:~/work$ ./tfftw3
0.0000000000000000
62.073801020876488
43.911688245431428
39.663452799755568
-54.000000000000000
-33.504073233321513
-57.911688245431428
31.766819412689461
16.000000000000000
5.0000000000000000
32.000000000000000
38.000000000000000
-33.000000000000000
-19.000000000000000
-10.000000000000002
1.0000000000000033
-7.9999999999999982
-20.000000000000000
10.000000000000002
-1.0000000000000040
3.9999999999999973
11.000000000000000
-1.0000000000000013
-7.0000000000000018
-1.9999999999999984
0.0000000000000000
33.141504861910015
-67.041630560342611
-95.619529124742456
-70.000000000000000
30.848508306793022
18.958369439657382
39.609542293445493
0.0000000000000000
5.0000000000000000
32.000000000000000
38.000000000000000
-33.000000000000000
-19.000000000000000
-10.000000000000000
1.0000000000000000
-8.0000000000000000
-20.000000000000000
10.000000000000000
-1.0000000000000000
4.0000000000000000
11.000000000000000
-1.0000000000000000
-7.0000000000000000
-2.0000000000000000
いろいろメモ
ubuntu10.04LTS/Intel fortran 11.0
・アポストロフィーを含む文字列の出力 (f77)
character*80 text1
text1="set dir=''0 0.01 0''"
L1=len_trim(text1)
write(10,'(a<L1>)') text1
5
<----- ここまでがフリエ変換の出力
<----- 逆変換された値は規格化する(1/N)
ダブルコーテーション (") 中のアポストロフィー (') は二重にする。
set dir='0 0.01 0'
f90 でのメモ
program gtest
implicit none
character ::text1*80,text2*80,ciday*80
integer iday,L1
iday=30
text1="set d='0 0.1 0.2'"
text2='opaq url'
write(*,'(a)') text1
write(*,'(a)') text2
write(ciday,*) iday
ciday=adjustl(ciday)
write(*,'(a)') trim(text2)//trim(ciday)//trim(text1)
L1=len_trim(text2)
write(*,'(a)') text2(1:L1)
end program gtest
6