割り当てられた配列をサブルーチンからFortranのメインプログラムに渡します。使用またはモジュール?インターフェース?

Aug 16 2020

サブルーチンに配列を割り当ててから、この配列をメインプログラムで使用して、他のサブルーチンに渡したいと思います。以前は(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

回答

2 francescalus Aug 16 2020 at 17:19

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

この場合、インターフェイスブロックを優先しないでください。

VladimirF Aug 16 2020 at 13:07

最初と最後の行のコピーのみをモジュールに配置しました。それはうまくいきません。サブルーチン全体をモジュールに移動する必要があります。