LoginSignup
3
0

More than 3 years have passed since last update.

コードを読み解いて学ぶFortran

Last updated at Posted at 2020-09-28

既存のFortranコードを読み解いて、理解を深めていく。(追記中)

変数宣言の上にあるuse

main1.f90
Program Main
  Use parameters
  Implicit none
  Real(8) :: a, b, c

  ...
  array(1) = a
  array(2) = b
  array(3) = c


End Program Main 

のように、変数宣言の前にあるuse文。これはmoduleという別に書いたコードで作った変数群、subroutine群、関数群をMainプログラムに呼び込むための文。例えば以下のようなモジュールを記載したコードを作っておいて、分割コンパイルすることが多い。(同じファイルの中にあっても、もちろん問題はない。)

parameters.f90
Module parameters
  Implicit none
  Real(8), parameter :: Ha = 27.21 !eV
  Real(8) :: array(1:3)

End Module parameter 

他のコードから呼ぶときuse parametersと書くと、parametersモジュールで宣言したすべての変数/subroutine/関数が呼び込まれる。
ちなみに、変数宣言の個所でparameterを付けると、定数となりその変数は書き換え不可能になる。数学定数や物理定数などをまとめておくのにも、モジュールはよく使われる。

有用な解説: 9. モジュールと構造型 — Fortran演習(地球惑星物理学演習)

use module, only:で読み込んだモジュールから必要な変数のみを読み込む

main2.f90
Program Main
  Use parameters, only: array
  Implicit none
  Real(8) :: a, b, c

  ...
  array(1) = a
  array(2) = b
  array(3) = c


End Program Main 

のように、onlyをつけることで、モジュールから、特定の変数、関数、サブルーチンのみを呼び出すことができる。
コードが巨大になり、複数人数が開発に携わるようになると、どのコードでどの変数、関数、サブルーチンが呼ばれているのかを把握することが困難になる。特に変数は、想定外の個所で値を変更してしまうと、思いもよらないところでトラブルを起こす。こういった問題を避けやすくするために、onlyをつけて読み込む変数を限定することができる。さらに、これはコードから様々な変数、機能がどこで使われているのかを把握しやすくすることができる。

use module, only: a => bで読み込んだ変数の名前をコード内でのみ変更する

main3.f90
Program Main
  Use parameters, only: array => vector
  Implicit none
  Real(8) :: a, b, c

  ...
  vector(1) = a
  vector(2) = b
  vector(3) = c


End Program Main 

のように、=>を使うことで、元のモジュールで使われていた変数、関数、サブルーチンの名前を、該当コード内では異なる名前として使うことができる。
ローカルな変数は、たとえ同じ名前が他の関数、サブルーチンで使われている変数と同じであっても、それらが混ざることはない。つまりローカルな変数はお互いに干渉せず、値の変更はお互いに反映されないし、そもそも型や配列の形、そもそも変数と関数という異なる対象のものであっても、問題はない。一方で、モジュールを読み込んだ場合は、デフォルトではモジュールで宣言されている変数の名前を使う必要がある。これが様々な理由で都合が悪い場合は、=>を使うことで、その関数、サブルーチンの中では異なる名前として参照することができる。例えば物理定数モジュールに光速度としてcがあり、対象のコードではa,bに引き続く変数としてcを用いたい場合Use phys_constants, only c => light_speedのように異なる変数名に変えることで、対象コード内のローカル変数としてcを使うことができる。

変数宣言の個所にあるallocatable

Fortranでは配列を宣言する方法が大きく分けて二通りある。一つは変数を宣言する際に形とサイズを指定するもの、もう一つは変数宣言時には形だけを指定して、具体的なサイズは実行時に指定する方法である。具体的なコードを以下に示す。

形とサイズを変数宣言時に指定する配列

main4.f90
Program Main
  Implicit none
  Real(8) :: array1(1:3), array2(1:2, 2:4)

End Program Main 

上のコードでarray1(1), array1(2), array1(3), array2(1, 2), array2(2, 2), array2(1, 3), array2(2, 3), array2(1, 4), array2(2, 4)を要素とする配列が定義できる。

形を変数宣言時に指定してサイズは実行時に決める配列

main5.f90
Program Main
  Implicit none
  Real(8), allocatable :: array3(:), array4(:,:)

  Allocate(array3(1:3))
  Allocate(array4(1:2, 2:4))

End Program Main 

上のコードでarray3(1), array3(2), array3(3), array4(1, 2), array4(2, 2), array4(1, 3), array4(2, 3), array4(1, 4), array4(2, 4)を要素とする配列が定義できる。
このように、実行途中で配列のサイズを指定するのは、コンパイル時点でサイズのわからない配列についての計算コードを書くためである。例えば、allocate文よりも前のどこかで、配列の大きさを指定するパラメーターを読み込み、それに応じて配列を確保する際に、使われる。

Module, subroutineの中にあるcontains

(書きかけ)

3
0
2

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
3
0