モジュールの初歩

モジュールの記述形式

  module モジュールの名称
     ... (モジュールの内容)
  end module モジュールの名称

モジュールサブルーチンの記述形式

  module モジュールの名称
     implicit none
  contains
     subroutine サブルーチンの名称(仮引数,仮引数,...) 
     ... (サブルーチンの内容)
     end subroutine サブルーチンの名称
     ... (他のサブルーチンも同様に記述できる)
  end module モジュールの名称

プログラミングのポイント

各プログラム単位内で,implicit none宣言を行うこと.

モジュール使用宣言

  use モジュールの名称

モジュールサブルーチンの使用例

! モジュールサブルーチンの使用例
!  分数の入出力を行うサブルーチン
!  分数の和を計算する関数
!
module bs ! モジュールの記述
  implicit none
! 構造体 bunsuuの定義
  type :: bunsuu
    integer :: bunsi, bunbo
  end type bunsuu
  contains !以下では構造体bunsuuが使える
!   分数の足し算を行う関数
    function  wa(a,b)
      implicit none
      type (bunsuu) :: wa
      type (bunsuu), intent(in) :: a,b
!     waの分子の計算
      wa%bunsi=a%bunsi*b%bunbo+b%bunsi*a%bunbo
!     waの分母の計算
      wa%bunbo=a%bunbo*b%bunbo
      return
    end function wa
!   分数の読み込みを行うサブルーチン
    subroutine yomu(ji,a)
      implicit none
      character(*), intent(in) :: ji
      type (bunsuu), intent(out) :: a
      write(*,*)ji
      read(*,*) a%bunsi, a%bunbo
      return
    end subroutine yomu
!   分数の書き出しを行うサブルーチン
    subroutine kaku(ji,a)
      implicit none
      character(*), intent(in) :: ji
      type (bunsuu), intent(in) :: a
      character(14) :: fmt='(1x,a,i3,a,i3)'
      write(*,fmt)ji,a%bunsi,'  /',a%bunbo
      return
    end subroutine kaku
end module bs
program ex03
  use bs !モジュールの使用宣言
! 以下では構造体bunsuuが使える.
  implicit none
  type (bunsuu) :: a,b,c,d,e,f
! 分数a,b,cを読み込む
  call yomu('a=',a)
  call yomu('b=',b)
  call yomu('c=',c)
  d=wa(a,b)
  e=wa(c,d)
  f=wa(wa(a,b),c)
  call kaku('a+b = ',d)
  call kaku('c+d = ',e)
  call kaku('a+b+c = ',f)
  stop
end program ex03

実行例

$ ex03
 a=
1,2
 b=
1,3
 c=
1,6
 a+b =   5  /  6
 c+d =  36  / 36
 a+b+c =  36  / 36

モジュールを使わない例

program ex02
!
! 構造体を扱うサブルーチンと関数の例
!  分数の入出力を行うサブルーチン
!  分数の和を計算する関数
!
  implicit none
! 構造体 bunsuuの定義
  type :: bunsuu
    integer :: bunsi, bunbo
  end type bunsuu
! bunsuu型の変数a,b,cの宣言
  type (bunsuu) :: a,b,c,d,e,f
! 分数a,b,cを読み込む
  call yomu('a=',a)
  call yomu('b=',b)
  call yomu('c=',c)
  d=wa(a,b)
  e=wa(c,d)
  f=wa(wa(a,b),c)
  call kaku('a+b = ',d)
  call kaku('c+d = ',e)
  call kaku('a+b+c = ',f)
  stop
contains !以下では構造体bunsuuが使える
!分数の足し算を行う関数
  function  wa(a,b)
    implicit none
    type (bunsuu) :: wa
    type (bunsuu), intent(in) :: a,b
!   waの分子の計算
    wa%bunsi=a%bunsi*b%bunbo+b%bunsi*a%bunbo
!   waの分母の計算
    wa%bunbo=a%bunbo*b%bunbo
   return
  end function wa
! 分数の読み込みを行うサブルーチン
  subroutine yomu(ji,a)
    implicit none
    character(*), intent(in) :: ji
    type (bunsuu), intent(out) :: a
    write(*,*)ji
    read(*,*) a%bunsi, a%bunbo
    return
  end subroutine yomu
! 分数の書き出しを行うサブルーチン
  subroutine kaku(ji,a)
    implicit none
    character(*), intent(in) :: ji
    type (bunsuu), intent(in) :: a
    character(14) :: fmt='(1x,a,i3,a,i3)'
    write(*,fmt)ji,a%bunsi,'  /',a%bunbo
    return
  end subroutine kaku
end program ex02

モジュール関数の使用例

! モジュール関数の使用例
!  血液型をABO型の区別とRh型の区別の組として扱う構造体
!  血液型が一致するか判定する関数
!
module blood_type ! モジュールの記述
  implicit none
! 構造体 btypeの定義
  type :: btype
    character(2) :: abo
    character(1) :: rh
  end type btype
  contains !以下では構造体btypeが使える
!   血液型が一致しているか確認する関数
    function  match(bt1,bt2) result (ma)
      implicit none
      type (btype), intent(in) :: bt1,bt2 !関数の引数
      character(9) ma !     関数の戻り値
      if ( (bt1%abo == bt2%abo) .and. (bt1%rh == bt2%rh) )then
        ma = 'Match'
      else
        ma = 'Not match'
      endif
      return
    end function match
end module blood_type
program ex04
  use blood_type !モジュールの使用宣言
  implicit none
  type (btype) :: bt1, bt2
! 文字型のmatchの宣言は不要
  bt1%abo='A'; bt1%rh='+'
  bt2%abo='A'; bt2%rh='+'
  write(*,*)bt1%abo, bt1%rh
  write(*,*)bt2%abo, bt2%rh
  write(*,*)match(bt1,bt2)
  write(*,*)
  bt1%abo='A'; bt1%rh='+'
  bt2%abo='A'; bt2%rh='-'
  write(*,*)bt1%abo, bt1%rh
  write(*,*)bt2%abo, bt2%rh
  write(*,*)match(bt1,bt2)
  stop
end program ex04

実行例

$ ex04
 A +
 A +
 Match   
 
 A +
 A -
 Not match

publicとprivateの使用例

!
! publicとprivateの使用例
!
module sample_mod
  implicit none
  private !モジュール内の全ての変数・サブルーチン・関数が外部から参照できなくなる.
  integer, save :: ia=1,ib=2
  public ib,sub !指定された変数などを外部から参照できるようにする.
contains
  subroutine sub
    integer, save :: id=4
    write(*,*)'sub: ia,id=',ia,id
  end subroutine sub
end module sample_mod
program chk_module
  use sample_mod
  implicit none
!!!  下の文をコメントアウトするとエラーになる(iaはsample_modの中でしか使えない)
!!!  write(*,*)'chk_module: ia=',ia
  write(*,*)'chk_module: ib=',ib
! モジュールsample_mod0の使用宣言を行うことにより,containsより前に宣言された
! サブルーチンsubを,他のプログラム単位で参照できる.
  call sub
!!!  下の文をコメントアウトするとエラーになる(idはsubの中でしか使えない)
!!!  write(*,*)'chk_module: id=',id
end program chk_module

実行例

$ ex06

chk_module: ib= 2

sub: ia,id= 1 4

エラーとなる例(外部から参照できない変数を参照しようとした)

!
! publicとprivateの使用例
!
module sample_mod
  implicit none
  private !モジュール内の全ての変数などは外部から参照できなくなる.
  integer, save :: ia=1,ib=2
  public ib,sub !指定された変数などを外部から参照できるようにする.
contains
  subroutine sub
    integer, save :: id=4
    write(*,*)'sub: ia,id=',ia,id
  end subroutine sub
end module sample_mod
program chk_module
  use sample_mod
  implicit none
!!!  下の文をコメントアウトするとエラーになる(iaはsample_modの中でしか使えない)
  write(*,*)'chk_module: ia=',ia
  write(*,*)'chk_module: ib=',ib
! モジュールsample_mod0の使用宣言を行うことにより,containsより前に宣言された
! サブルーチンsubを,他のプログラム単位で参照できる.
  call sub
!!!  下の文をコメントアウトするとエラーになる(idはsubの中でしか使えない)
  write(*,*)'chk_module: id=',id
end program chk_module

コンパイル例

ifort -c -CB -traceback -fpe0 -r8 ex06.f90
ex06.f90(21): error #6404: This name does not have a type, and must have an explicit type. [IA]
write(*,*)'chk_module: ia=',ia
------------------------------^
ex06.f90(30): error #6404: This name does not have a type, and must have an explicit type. [ID]
write(*,*)'chk_module: id=',id
------------------------------^