【Fortran学習|初心者向け】Fortranで実現する「多態性」:`class`と`select type`でプログラムをスマートにする方法

1. 導入:なぜ「多態性」が重要なのか

数値計算のプログラムを書いていると、「似ているけれど計算式が少し違う」複数のモデルを扱うことがよくあります。例えば、「流体モデルA」と「流体モデルB」で、flux(流束)を計算する関数を別々に作ると、メインプログラムが条件分岐だらけになり、管理が非常に大変になります。
「多態性(ポリモーフィズム)」を使えば、共通のインターフェースでモデルを呼び出せるようになり、コードの保守性が劇的に向上します。今回は、Fortranの`class`引数と`select type`構文を使った、スマートな実装方法を解説します。

2. 基礎知識:多態性とは?

多態性とは、一つの手続き(関数やサブルーチン)が、受け取るデータの型に応じて「適切な動作を自動的に選択する」性質のことです。
Fortranでは、基底となる型を`class(base_model)`として引数に指定することで、その子孫にあたる様々な型のデータを受け取れるようになります。受け取った先で`select type`構文を使うと、「今渡されたのはどのモデルなのか?」を判断し、実行時に最適な処理を切り替えることができます。

3. 実装と解決策

実装のステップは以下の通りです。
1. 基底となる`type`を定義する。
2. 派生型で、基底型を継承する。
3. 手続きの引数を`class`型にして、`select type`で型を判別して計算式を切り替える。

これにより、新しいモデルを追加しても、メインの呼び出し側コードを書き換える必要がなくなります。

4. サンプルプログラム

以下のコードは、異なる物理モデルのfluxを一つのサブルーチンで計算する例です。

module physics_models
  implicit none

  ! 基底型:すべてのモデルの親
  type, abstract :: base_model
  end type

  ! モデルA:例として線形モデル
  type, extends(base_model) :: linear_model
  end type

  ! モデルB:例として非線形モデル
  type, extends(base_model) :: nonlinear_model
  end type

contains

  ! 多態性を利用した手続き
  subroutine calc_flux(this)
    class(base_model), intent(in) :: this

    ! 実行時の型に応じて処理を振り分ける
    select type (this)
    type is (linear_model)
      print , "線形モデルのflux計算を実行中..."
      ! ここに線形用の計算式を書く
    type is (nonlinear_model)
      print , "非線形モデルのflux計算を実行中..."
      ! ここに非線形用の計算式を書く
    class default
      print , "未対応のモデルです"
    end select
  end subroutine
end module

program main
  use physics_models
  type(linear_model) :: model_a
  type(nonlinear_model) :: model_b

  ! 同じ手続き名で異なる計算が呼び出せる
  call calc_flux(model_a)
  call calc_flux(model_b)
end program

5. 応用・注意点:現場で役立つポイント

注意点: `select type`は非常に便利ですが、使いすぎると計算速度に影響が出る場合があります。特に計算のループの中で毎回型判定を行うとオーバーヘッドが大きくなるため、可能な限り「計算ループの外側」で型を決定し、ループ内では最適化された手続きを呼び出すのがコツです。

回避策: もし計算速度が極端に重要な場合は、`select type`の代わりに「型ごとの手続きポインタ」を事前に割り当てておく手法(vtableのような仕組み)も検討してみてください。まずはこの`select type`でコードの整理を進め、ボトルネックが発生した際に最適化を行うのが、初心者の方にとって最も安全で確実なステップアップです。

コメント

タイトルとURLをコピーしました