Fortran90で構造体を使う

Fortran90で自分で型を定義し、それを使用します。
本稿でいう”型”は、一般には構造体と呼ばれます。
Fortran使用者にとっては”型”という名称が分かりやすいでしょう。

整数型、倍精度型などと同列にあるもの、と考えて差し支えないです。

本稿では基本的なことしか書いていません。

二階偏微分の計算の時でも構造体の考えを使用していますので、もう少し例が欲しい方はこちらもどうぞ。
Hyper-dual numbersによる二階偏微分の計算 -シキノート

概要

簡単な実例



module CEOM_mod
  implicit none
  type Particle
     double precision::m,x,v
  end type Particle
end module CEOM_mod

program main
  use CEOM_mod
  implicit none
  type(Particle)::p1

  p1%m  = 1d0
  p1%x  = 2d0
  p1%v  = 3d0

  write(6,*)p1%m,p1%x,p1%v

  stop
end program main

実行結果

$ ./a.out
   1.0000000000000000        2.0000000000000000        3.0000000000000000
$

説明


上は、粒子p1が質量m, 位置x, 速度vを持つ、ということを想定しています。

そこで、Particleという新しい”型”(複素数型みたいに、実部と虚部という2つの独立な変数を1つの複素数型変数が持つ、みたいな変数の型)を定義しました。
Particle型を持つ変数は、すべてm, x, vを内包するというイメージです。

mainプログラムではparticle型が定義されているモジュールを呼び出すために

    use CEOM_mod

という文を入れ、実際にparticle型の変数p1を定義するために

  type(Particle)::p1

と書いています。変数p1が定義されると自動的にp1が持つm,x,vの固有な値も定義されます。固有の値をいじる場合は

  p1%m  = 1d0

と書いて、変数に%をつけてm,x,vのいずれかを書いて代入します。


配列



module CEOM_mod
  implicit none
  type Particle
     double precision::m,x,v
  end type Particle
end module CEOM_mod

program main
  use CEOM_mod
  implicit none
  integer::i,N
  type(Particle),allocatable::p(:)

  N=5
  allocate(p(1:N))
  do i=1,N
     p(i)%m  = 1d0
     p(i)%x  = dble(i)
     p(i)%v  = 0.1d0*i
  enddo

  do i=1,N
     write(6,*)i,p(i)%m,p(i)%x,p(i)%v
  enddo

  stop
end program main

実行結果

$ ./a.out
                    1   1.0000000000000000        1.0000000000000000       0.10000000000000001<br />
                    2   1.0000000000000000        2.0000000000000000       0.20000000000000001<br />
                    3   1.0000000000000000        3.0000000000000000       0.30000000000000004<br />
                    4   1.0000000000000000        4.0000000000000000       0.40000000000000002<br />
                    5   1.0000000000000000        5.0000000000000000       0.50000000000000000
$

サブルーチンの利用



module CEOM_mod
  implicit none
  type Particle
     double precision::m,x,v
  end type Particle
end module CEOM_mod

subroutine twicemass(N,p)
  use CEOM_mod
  implicit none
  integer,intent(in)::N
  type(Particle),intent(inout)::p(1:N)

  integer::i
 
  do i=1,N
     p(i)%m  = 2 * p(i)%m
  enddo
 
  return
end subroutine twicemass

program main
  use CEOM_mod
  implicit none
  integer::i,N
  type(Particle),allocatable::p(:)

  N=3
  allocate(p(1:N))
  do i=1,N
     p(i)%m  = 1d0
     p(i)%x  = dble(i)
     p(i)%v  = 0.1d0*i
  enddo

  call twicemass(N,p)
 
  do i=1,N
     write(6,*)i,p(i)%m,p(i)%x,p(i)%v
  enddo

  stop
end program main

実行結果

$ ./a.out
                    1   2.0000000000000000        1.0000000000000000       0.10000000000000001<br />
                    2   2.0000000000000000        2.0000000000000000       0.20000000000000001<br />
                    3   2.0000000000000000        3.0000000000000000       0.30000000000000004<br />
$

補足


オブジェクト指向になれている方は、構造体の中身を外部から直接アクセスできる点で褒められた書き方ではないでしょう。
Fortran90にオブジェクト指向の考え方を持ってくるのは、計算速度というFortran90の長所を潰してしまうので、このくらいで良いでしょう。