ミケガモのブログ

プログラミング言語「fortran」のメモ。

全てfortran90のもの。

配列

多次元配列(行列)の初期化

値を入れながら多次元配列を宣言するときは、

A(m,n) = (1次元配列).reshape(shape(A))

とする。配列の中に配列を入れる、という一般的な形での宣言は受け付けてくれない。

さらにここで、悪名高きfortranの多次元配列代入の仕様に注意。reshapeやファイルのreadなどで1次元の数列を多次元配列に初めから代入していく場合、代入される場所は(1,1), (2,1), (3,1)...という順である(普通の言語なら(1,1),(1,2),...となるところ)。例えば

A = (/1,2,3,4,5,6/).reshape(3,2)

を実行すると、結果は

((1,3,5), (2,4,6))

である。

特定行へのアクセス

「ある行をn倍したい」という時など、行の成分をまとめて処理する際は

 A(1,:) = A(1,:)*0.5

のような書き方が可能である。

size,shape関数

size(配列, 次元)

で、任意の次元の要素数を取得できる。例えばある2次元配列で、各行に対しループを回したいときは

do i = 1, size(A, 1)
  (処理)
enddo

としよう。次元のオプションをつけないと、全要素数が返ってくるので注意(3x2行列なら"6"が返る)。

shape関数は、配列の次元を一次元配列で返す。sizeが使えればあんまり出番が無さそう。

if文

if (条件 1) then
  aaa
else if (条件 2) then
  bbb
else
  zzz
end if

条件式を( )でくくる。最後のelseにはthenがいらない。 基本的な構文なのにも関わらず、ググった回数は数知れず。

allocate/deallocate

deallocate文は、一度宣言したallocatable配列の長さをリセットできる。再度allocateすれば、配列の長さを前回から変更することも可能。 ループごとに異なる要素数の配列を用意したいときに有用だった。

real(8),allocatable :: matrix(:,:)
 allocate(matrix(10,15))
~~~
 deallocate(matrix)
 allocate(matrix(20,30))
~~~

ファイル名に番号を割り当てて保存

変数の値ごとに別のファイルに計算結果を書き出す際に使ったコード。 文字列の扱いにはあまり強くないfortranは、

  • character型は長さを手動で宣言しなければならない。
  • char(x) のような構文が使えない。

そのためここでは、

  1. 十分長い文字列を用意する。
  2. 目的の数値をcharacter型に代入する。
  3. trim関数で文字列の余り部分をトリミングする。

という手順を踏んでいる。

real(8) :: x = 1.2d0
integer :: ios
character(len=30) :: filename, fullname

filenum = int(x*10)
write(filename,'(i0)') filenum ! point1: 整数型のfilenumを文字列型のfilenumに書き込み(代入)
fullname = trim('result'//trim(filename)//'.txt') ! point2: trim関数で文字列の余白部分をトリミング
open(unit=filenum, iostat=ios, file=fullname, action='write', form='formatted', status='replace')
if (ios /= 0) then
  write(*,*) 'Failed to open file', filenum
  stop
end if

名前を指定してファイルを開くサブルーチン

character(len=*) :: name とすることで、任意の長さの文字列を引数に取ることができる。

subroutine open_file_read(filename_strings, filenum_integer)
  integer :: filenum_integer, fileopen_ios
  character(len=*),INTENT(IN) :: filename_strings
    character(len=30) :: filenum_strings
    write(filenum_strings,'(i0)') filenum_integer !整数を文字列型に変換
    open(unit=filenum_integer, iostat=fileopen_ios, file=filename_strings, action='read', form='formatted', status='old')