割り当てられた配列をサブルーチンからFortranのメインプログラムに渡します。使用またはモジュール?インターフェース?
サブルーチンに配列を割り当ててから、この配列をメインプログラムで使用して、他のサブルーチンに渡したいと思います。以前は(F77?)共通のブロックで受け渡しを行うことができましたが、現在ではモジュールを使用するのが好ましい手順のようです。これを試してみると、コード例のように、コンパイラは私に教えてくれます
Rank mismatch in argument ‘f’ at (1) (scalar and rank-1)
どうやら、メインプログラムは 'f'がスカラーであると考えています:しかし、私はこのコードを、サブルーチン内とメインプログラムの両方で1次元配列として宣言したことを意味するように読みました。何が足りないのですか?
モジュールの一部として変数を宣言するなどのバリエーションを試しましたが、コンパイルにエラーが発生しないようにすることは考えられませんでした(さらに多くのエラーが発生するものもありました;-()。どんな洞察も大歓迎です。
module subs
contains
subroutine makef(f)
end subroutine makef
end module subs
c-----------------------------------------------------------------------
program work
use subs
implicit none
real, allocatable :: f(:)
call makef(f)
write (*,*) f
stop
end
c---------------------------------------------------------------------
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
return
end subroutine makef
回答
Fortranのモジュールは、他の言語で定義されているものに関する情報を提供するだけの他の言語のヘッダーファイルとは異なります。「据え置き定義」(サブモジュール)の概念がありますが、この場合、モジュールは、単にその存在を指摘しようとするのではなく、サブルーチンに関するすべてを言う必要があります。
質問の例では、次のものがあります。メインプログラム。モジュールsubs
モジュール手順makef
。外部サブルーチンmakef
。
メインプログラムはモジュールsubs
とそのプロシージャを使用するmakef
ため、メインプログラムでの参照makef
は、外部サブルーチンではなく、そのモジュールプロシージャmakef
です。
モジュールサブルーチンにmakef
は、f
宣言ステートメントを持たない引数があり、暗黙的に宣言されたスカラー/外部関数になります。これはコンパイラのメッセージです。implicit noneここのメインプログラムと外部サブルーチンと同じように、モジュールで使用します。
サブルーチンの定義全体をモジュールに配置する必要があります。
module subs
implicit none
contains
subroutine makef(f)
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
end subroutine makef
end module subs
あるいは、外部プロシージャの後での実装を参照したい場合は、サブルーチン自体を宣言せずに、インターフェイスブロックをモジュールで機能させることができます。この場合でも、完全なインターフェースを指定する必要があります。
module subs
implicit none
! An interface block to give an explicit interface to the external subroutine makef
interface
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
end subroutine makef
end interface
end module subs
この場合、インターフェイスブロックを優先しないでください。
最初と最後の行のコピーのみをモジュールに配置しました。それはうまくいきません。サブルーチン全体をモジュールに移動する必要があります。