0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Fortranの基本ざっくりまとめ

Posted at

はじめに

研究で主にJulia, Pythonを使っていたのですが、私がずっと逃げてきたfortranを触る必要が出てきたので、ざっとfortranコードを読めて書くための基本をまとめました。

この記事で分かること
  • ざっくりとfortranの書き方, 動かし方が分かる
  • 変数の型定義
  • 配列
  • ループ系の文法
  • ファイル入出力
  • 標準入出力
  • 関数の書き方
  • サブルーチンの書き方
  • モジュールの書き方

書き方

基本的には以下の例のようなプログラム構成になります。
例として、1~10の総和を取って標準出力にprintするプログラムを載せました。

program main
    implicit none ! 暗黙の変数の型に関する規則(変数の先頭がi~nまでだと整数、それ以外では実数になるという規則)を無効にする

    ! ---------変数定義 ----------------------------------------
    integer :: i
    real(8) :: nums(10)
    real(8) :: total

    ! ---------実行文 ----------------------------------------
    total = 0.d0
    do i = 1, 10
            nums(i) = i
    enddo
    total = sum(nums)

    write(*, *) 'total = ', total ! 他の言語でいうprint文
    ! write(ファイル番号, 書式) 出力対象1, 出力対象2,,,
    ! ファイル番号に* -> 標準出力
    ! 書式に* -> 並び出力(write文の後に並ぶ変数の型にあった書式で出力される)

end program main
  • implicit none
    おまじないなので、必ず書く。
    意味としては、暗黙の変数の型に関する規則(変数の先頭がi~nまでだと整数、それ以外では実数になるという規則)を無効にするというものになります。

プログラム実行方法

fortranはコンパイルしてから実行するので、gfortran ファイル名.f90でコンパイルします。
その後、a.outというコンパイルされたファイルが作成されます。
これを実行すればプログラムを実行することができます。

$ gfortran main.f90 #コンパイル
$ ./a.out #プログラム実行
total =    55.000000000000000

変数

型 :: 変数名
  • 実数
    • 単精度実数(32bit, 6-7桁) real
    • 倍精度実数(64bit, 14-16桁) real(8)
  • 複素数型
    • 単精度 complex
    • 倍精度 complex
配列

配列にするときは、型 :: 変数名(要素数) にすればOK.

real(8) :: numbers(100)
real(8) :: matrix(10, 10) !多次元配列
割付け配列

配列のサイズが初期設定として定まらない時には、allocatableという属性をつけると
後からサイズを定義することができる。

real(8), allocatable :: r(:)
integer :: n = 2

allocate (r(n)) ! n=2を割り付ける
! hoge
deallocate (r) ! 割付を解除する

構造体

自分で定義できる型。
複数の型を要素として持つことができる。

type :: name
    integer :: nums
    real(8) :: total
end type name

do, while, if

! doループ
do i = min, max
    ! 実行文
enddo

! while ループ
do while (condition)
    ! 実行文
end do

! if文
if (論理式) then
    ! 実行文
else if (論理式) then
    ! 実行文
else
    ! 実行文
    ! ex)
    stop 'error! something is wrong!' !stop文を使うとエラーを検知できる
endif

ファイル入出力

! 入力
open(10, file='input.dat') ! ファイル番号10で入力ファイルinput.datを開く
read(10, *) x1 ! 1行目の値をx1に代入
read(10, *) x2 ! 2行目の値をx2に代入
close(10) ! ファイルを閉じる

! 出力
open(20, file='output.dat', status='replace') ! ファイル番号20でoutput.datを開く
write(20, *) result1, result2 ! 出力する
close(20) 

ファイル番号は任意でOkです.
出力する時のopen(ファイル番号,file=ファイル名, status='?')のstatus:

  • old: 事前にファイルが存在している
  • new: 事前に存在してはいけない
  • replace: 事前に存在していてもしなくてもどっちでもOK

標準入出力

integer :: i
! 入力
read(*,*) i ! 標準入力のinputされた値をiに代入する
! 出力
write(*,*) 'your input i = ', i ! 「your input i = iの値」を標準出力する

副プログラム編

module, subroutine, functionを理解するために以下のプログラムをみてください。
内容は最初のプログラムを同じで1からnまでの総和を取るだけです。
それをmodule, subroutine, functionを使って書いています。

module utils
    implicit none
    
contains
    ! subroutine
    ! 配列の総和を計算する
    subroutine calc_total(nums, n, total)
    implicit none
    integer, intent(in) :: n
    real(8), intent(in) :: nums(n)
    real(8), intent(out) :: total

    total = 0.d0
    total = sum(nums) ! 総和をとる
    
    end subroutine calc_total

    ! function
    ! 1からnまでを要素として格納した配列を返す
    function make_nums(n) result(nums)
        implicit none
        integer, intent(in) :: n
        real(8) :: nums(n)
        integer :: i

        ! 配列に1からnを追加する
        do i = 1, n
            nums(i) = i
        end do
        
    end function make_nums
end module utils

program main
    use utils ! moduleを呼び出す
    implicit none ! 暗黙の変数の型に関する規則(変数の先頭がi~nまでだと整数、それ以 外では実数になるという規則)を無効にする

    ! ---------変数定義 ----------------------------------------
    integer :: i
    integer :: n
    real(8), allocatable :: nums(:)
    real(8) :: total
    !real(8) :: factor
    integer, parameter :: XNUM = 100
    real(8) :: xs(XNUM), ys(XNUM)

    ! ---------実行文 ----------------------------------------
    
    !標準入力
    write(*,*) 'input n : '
    read(*,*) n

    ! 配列numsのサイズをnに割り当てる
    allocate(nums(n))

    ! function
    ! 1からnを配列numsに格納する
    nums = make_nums(n)

    ! subroutine
    ! 配列numsの要素の総和を計算してtotalに代入する
    call calc_total(nums, n, total)

    ! 配列numsを解放する
    deallocate(nums)
    
    ! 標準出力
    ! write(ファイル番号, 書式) 出力対象1, 出力対象2,,,
    ! ファイル番号に* -> 標準出力
    ! 書式に* -> 並び出力(write文の後に並ぶ変数の型にあった書式で出力される)
    write(*, *) 'total = ', total

    ! ファイル出力
    open(20, file='output.dat', status='replace')
    write(20,*) total
    close(20) 

end program main

Subroutine

  • 書き方
subroutine function_name(arg1, arg2, arg3)
    implicit none
    , intent(in) :: arg1
    , intent(in) :: arg2
    , intent(out) :: total
    ! 実行文
    end subroutine calc_total
  • 呼び出し方
call subroutine(arg,,,)
  • 説明
    • サブルーチン内でのみ使う引数(仮引数)にはintent(in)属性をつける
    • サブルーチン呼び出し後に戻る変数にはintent(out)属性をつける
    • 前回の値を保持させるには、save属性をつける

Function

  • 書き方
function name(args,,,) result(output)
    implicit none
    ! 変数宣言
    , intent(in) :: arg
    ,,,,
     :: output

    !実行文
end function name
  • 呼び出し方
function_name(引数,,,)
  • 説明
    • 関数は単一の変数(output)を返し、引数に演算結果を格納しない
    • result句内の変数を返す
    • 返す変数は決まっているため、intent(in)属性だけ付ける

module

  • 書き方
module name
    implicit none
contains
! 中身
! submodule, functionなど
end module name
  • 呼び出し方
use module_name
  • 補足
    • module内でグローバル変数を定義するときは、save属性をつける

参考

数値計算のためのFortran90/95プログラミング入門, 牛島省, 森北出版株式会社

0
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?