1
0

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] モジュール メモ

Last updated at Posted at 2020-06-14

コンパイラはifort.
単語帳.毎回検索するのが面倒なので転載多め.元URLあり.
自前の検証メモも.

他ファイルの手続きをそのまま渡す

mymod1.f90にあるmysubという手続きをmymod2.f90でuseすると,他ファイルからはuse mymod2, only: mysub1で使える

mymod1.f90
module mymod1
    implicit none

contains

subroutine mysub1
    write(*, *) 'hello'
end subroutine mysub1
end module mymod1
mysub2.f90
module mymod2
    use mymod1, only: mysub1 ! only以降ははなくても可
end module mymod2
main.f90
program main
    use mymod2, only: mysub1
    implicit none
    call mysub1 ! hello
end program main

use, onlyで複数モジュールに重複した名前を定義可能

module mod10
    implicit none
    integer :: a = 10
end module mod10

module mod20
    implicit none
    integer :: a = 20
end module mod20

program main
    use mod10, only: a
!    use mod20, only: a
    implicit none
    write(*, *) a ! 10,もしmod10をコメントアウト+mod20を使うと20
end program main

使い方1

only句で使用する変数を明示するのが良いと考えられる.
なぜなら,これを省略するとコンパイルエラー(コンパイル時に検出してくれるのでありがたい)になるが,エラーの出る箇所は書き方によって変わるからである↓↓

! パターン1
    use mod10, only: a
    use mod20, only: a ! ここでエラー

! パターン2
    use mod10!, only: a
    use mod20, only: a ! ここでエラー

! パターン3
    use mod10, only: a ! ここでエラー
    use mod20!, only: a

! パターン4
    use mod10!, only: a
    use mod20!, only: a
    implicit none
    write(*, *) a ! ここでエラー

使い方2

重複した変数の両方を使いたい場合,別名で参照する:
@septcolorさんありがとうございます!)

program main
    use mod10, only: a10 => a
    use mod20, only: a20 => a
! use mod10, only: a10 => a, aをするとa10もaも(10として)使えるが…
    implicit none
    write(*, *) a10, a20 ! 10 20
!    write(*, *) a ! 本来の変数名は使えない
end program main

独立した関数と構造体のメソッドの速度は変わらない

これを使うと関数・サブルーチンの階層化が可能!?
以下の例の時間計測結果:

ケース no option [sec] -flto [sec] -ip [sec] -ipo [sec]
関数を直接使用 5.82 5.81 5.81 5.86
構造体のメソッド使用 5.89 5.89 5.90 5.94
  • 関数を直接使用する方が1%程度高速
    • 構造体経由の方が可読性が向上するなら許容範囲?
  • link-time optimization関連のコンパイルオプションによる変化は小さい
    • @septcolorさんありがとうございます!
  • 他のコンパイルオプションとの組み合わせ,構造体の中身が複雑化したときの速度は未検証
  • 式は[Qiita@hanaata: 色々な言語で計算速度を比較してみた]
    (https://qiita.com/hanaata/items/c91788bcac2a40f1bb05)を参照
module mymod
    implicit none

    type Funcs
        contains
        procedure :: mymethod => mymethod
    end type Funcs

    type(Funcs) :: myobj
contains

function myfunc(i) result (y) ! これが使いたい関数
    integer, intent(in) :: i
    real(8) :: y
    y = (-1.d0) ** dble(i) * (2.d0 * dble(i) + 1.d0) ** 0.1d0
end function myfunc


function mymethod(self, i) result(y) ! 中身は上の関数と同じだが構造体経由でアクセスする用
    class(Funcs), intent(in) :: self
    integer, intent(in) :: i
    real(8) :: y
    y = (-1.d0) ** dble(i) * (2.d0 * dble(i) + 1.d0) ** 0.1d0
end function mymethod

end module mymod


program main
    use mymod, only: myfunc, myobj
    implicit none
    integer, parameter :: n = 100, niter = 10
    integer :: itime, ix, iy, i, iiter
    real(8) :: a(n,n), time(niter)
    integer :: t1, t2, t_rate, t_max, diff
! 関数を直接使用
    time(:) = 0.d0
    do iiter = 1, niter
        call system_clock(t1)
        do itime = 1, 10 ** 4
            do iy = 1, n
                do ix = 1, n
                    do i = 0, n
                        a(ix,iy) = a(ix,iy) + myfunc(i)
                    enddo
                enddo
            enddo
        enddo
        call system_clock(t2, t_rate, t_max)
        if ( t2 < t1 ) then
            diff = (t_max - t1) + t2 + 1
        else
            diff = t2 - t1
        endif
        time(iiter) = diff / dble(t_rate)
    enddo
    write(*, *) sum(time) / dble(niter)

! 構造体のメソッド使用
    time(:) = 0.d0
    do iiter = 1, niter
        call system_clock(t1)
        do itime = 1, 10 ** 4
            do iy = 1, n
                do ix = 1, n
                    do i = 0, n
                        a(ix,iy) = a(ix,iy) + myobj%mymethod(i)
                    enddo
                enddo
            enddo
        enddo
        call system_clock(t2, t_rate, t_max)
        if ( t2 < t1 ) then
            diff = (t_max - t1) + t2 + 1
        else
            diff = t2 - t1
        endif
        time(iiter) = diff / dble(t_rate)
    enddo
    write(*, *) sum(time) / dble(niter)
end program main
1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?