【入門編】ABSTRACT INTERFACEとプロシージャポインタ – モダンFortran言語仕様と実践実践マスター

Fortranの「動的」な力:ABSTRACT INTERFACEとプロシージャポインタでコードを自在に操る

皆さん、こんにちは。かつて宇宙の深淵を数値計算で追いかけていた元・特任最高数値計算アーキテクトです。

「Fortranは古臭い」「静的すぎて柔軟性がない」……そんな誤解を抱えていませんか? C言語の関数ポインタやPythonのデコレータに慣れた皆さんにこそ知ってほしい、Fortranの隠れた武器があります。それが`ABSTRACT INTERFACE`と`PROCEDURE POINTER`です。

これらを使いこなせば、コンパイル時にすべてが決まる硬直したコードから脱却し、シミュレーションの最中にアルゴリズムを切り替えるような、モダンで「動的」な設計が可能になります。今日は、この泥臭くも強力な世界へご案内します。

1. そもそも「抽象インターフェース」って何?

PythonやC++などの他言語では、「関数を引数として渡す」ことは日常茶飯事ですよね。Fortranでこれを行うには、「渡そうとしている関数は、こういう引数構成(型、次元、intentなど)を持っていますよ」という「契約書」をコンパイラに事前に見せておく必要があります。

これが`ABSTRACT INTERFACE`です。いわば、「この形の関数なら何でも受け付けますよ」という設計図ですね。

! 抽象インターフェース:関数の「形(インターフェース)」を定義する
ABSTRACT INTERFACE
FUNCTION solver_func(x) RESULT(y)
REAL, INTENT(IN) :: x
REAL :: y
END FUNCTION solver_func
END INTERFACE

このブロック自体はコードとして実行されません。しかし、この定義があることで、コンパイラは「このルールに適合する関数なら、後から差し替えても安全だ」と判断できるようになります。

2. プロシージャポインタで「関数を入れ替える」

次に、このインターフェースを利用する「入れ物(ポインタ)」を作ります。これが`PROCEDURE POINTER`です。

「ポインタ」という言葉に身構える必要はありません。ここでは、「関数への参照を格納できる箱」と考えてください。

! インターフェースを利用する変数(プロシージャポインタ)を宣言
PROCEDURE(solver_func), POINTER :: my_algorithm => NULL()

これで準備完了です。実行時に、計算対象の関数をこの箱に代入するだけで、計算ロジックを自在に切り替えられます。

3. 実践:シミュレーションでの切り替え例

例えば、非線形方程式のソルバーで「手法A(ニュートン法)」と「手法B(二分法)」を切り替えるような場面を想像してください。

MODULE math_module
ABSTRACT INTERFACE
FUNCTION model_func(x) RESULT(y)
REAL, INTENT(IN) :: x
REAL :: y
END FUNCTION model_func
END INTERFACE

CONTAINS
! 物理モデル1
FUNCTION linear_model(x) RESULT(y)
REAL, INTENT(IN) :: x
y = 2.0 x
END FUNCTION linear_model

! 物理モデル2
FUNCTION quad_model(x) RESULT(y)
REAL, INTENT(IN) :: x
y = x2
END FUNCTION quad_model
END MODULE math_module

PROGRAM main
USE math_module
! プロシージャポインタの宣言
PROCEDURE(model_func), POINTER :: current_model => NULL()

! 状況に応じてアルゴリズムを切り替える
current_model => linear_model
PRINT , “結果1:”, current_model(5.0)

current_model => quad_model
PRINT , “結果2:”, current_model(5.0)
END PROGRAM main

4. 現場の教訓:なぜこれが必要なのか?

皆さんがこれから挑む大規模な数値計算の現場では、「コードの疎結合化」が死活問題になります。

  • コンパイラの最適化フラグへの影響: プロシージャポインタ経由の呼び出しは、直接呼び出しに比べてコンパイラが「どの関数が呼ばれるか」を静的に確定しにくいため、過度なインライン化が抑制される場合があります。しかし、それは「再コンパイルなしでアルゴリズムを差し替えられる」という巨大なメリットとのトレードオフです。
  • キャッシュ効率の罠: あまりに関数を細分化して頻繁に差し替えると、命令キャッシュに負荷がかかります。しかし、現代のCPUであれば、ループの外側でポインタをセットし、内側で呼び出す設計にすれば、ペナルティは無視できるレベルです。

最後に:まずは手を動かそう

まずは、今日紹介したコードをコピー&ペーストして、`gfortran`や`ifort`でコンパイルしてみてください。

コンパイルコマンド例
gfortran -O3 -Wall -o simulation main.f90
./simulation

最初はエラーが出るかもしれません。でも、そのエラーこそが「Fortranという堅牢な言語が、皆さんの設計ミスを未然に防いでくれている」証拠です。

Fortranは、単なる「古い計算用言語」ではありません。適切に使えば、C++並みの柔軟性と、圧倒的な計算速度を両立できるモダンなツールです。皆さんの研究や業務が、この「動的なFortran」でさらに加速することを期待しています!

何か詰まったら、いつでも聞いてくださいね。現場の知見を詰め込んだ回答でお返しします。

コメント

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