web-dev-qa-db-ja.com

割り当て可能な配列をFortranのサブルーチンに渡す方法

次のコードは、私が渡そうとしている割り当て可能な配列が正しく認識されていないため、セグメンテーション違反を返しています(サイズが3であるはずのサイズが1を返します)。このページ(http://www.eng-tips.com/viewthread.cfm?qid=170599)では、同様の例がF95で正常に機能することを示しているようです。私のコードファイルには.F90拡張子が付いていますが、それをF95に変更してみました。コンパイルにはgfortranを使用しています。

私の推測では、問題は割り当て可能な配列をサブルーチンに渡す方法にあるはずです。何が悪いのですか?

!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
 PROGRAM test
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
 IMPLICIT NONE
 DOUBLE PRECISION,ALLOCATABLE :: Array(:,:)
 INTEGER                      :: iii,jjj

 ALLOCATE(Array(3,3))
 DO iii=1,3
 DO jjj=1,3
    Array(iii,jjj)=iii+jjj
    PRINT*,Array(iii,jjj)
 ENDDO
 ENDDO
 CALL Subtest(Array)

 END PROGRAM
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
 SUBROUTINE Subtest(Array)
 DOUBLE PRECISION,ALLOCATABLE,INTENT(IN) :: Array(:,:)
 INTEGER                                 :: iii,jjj

 PRINT*,SIZE(Array,1),SIZE(Array,2)
 DO iii=1,SIZE(Array,1)
 DO jjj=1,SIZE(Array,2)
    PRINT*,Array(iii,jjj)
 ENDDO
 ENDDO

 END SUBROUTINE
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
17
Nordico

プロシージャに割り当て可能な仮引数がある場合、呼び出しスコープには明示的なインターフェイスが必要です。

(明示的なインターフェースを必要とするものは数多くありますが、割り当て可能なダミーは1つにすぎません。)

メインプログラム内にサブルーチンのインターフェイスブロックを配置することで、明示的なインターフェイスを自分で提供できます。代替のはるかに優れたオプションは、サブルーチンをモジュール内に配置し、そのモジュールをメインプログラムで使用することです。これにより、明示的なインターフェイスが自動的に作成されます。この例は、リンクを提供したeng-tipsサイトにあります。xwbによる投稿を参照してください。

割り当てステータスに関連する何かを行う場合(そのステータスのクエリ、再割り当て、割り当て解除など)を行う場合にのみ、仮引数が割り当て可能な属性を持つことは意味があることに注意してください。

31
IanH

また、割り当て可能な仮引数arrayintent(in)で宣言されていることにも注意してください。これは、割り当てステータスが関連する実際の引数の割り当てステータスになることを意味します(手順中に変更することはできません)。サブルーチンに渡される実際の引数は、割り当てられていない可能性があるため、明示的なインターフェイスを使用していても、参照することはできません。コンパイラーはこれを認識せず、sizeなどの問い合わせの動作はそのような場合は未定義です。

したがって、内容を参照する前に、まずarrayの割り当て状況をallocated(array)で確認する必要があります。さらに、lbounduboundを使用して配列全体にループを実装することをお勧めします。これは、一般にarrayの境界について確信が持てないためです。

subroutine subtest(array)
  double precision, allocatable, intent(in) :: array(:,:)
  integer                                   :: iii, jjj

  if(allocated(array)) then
    print*, size(array, 1), size(array, 2)
    do iii = lbound(array, 1), ubound(array, 1)
      do jjj = lbound(array, 2), ubound(array, 2)
        print*, array(iii,jjj)
      enddo
    enddo
  endif  
end subroutine
7
sigma

これは、モジュールで割り当て可能な仮引数を使用する簡単な例です。

module arrayMod   
  real,dimension(:,:),allocatable :: theArray    
end module arrayMod

program test
   use arrayMod
   implicit none

   interface
      subroutine arraySub
      end subroutine arraySub
   end interface

   write(*,*) allocated(theArray)
   call arraySub
   write(*,*) allocated(theArray) 
end program test

subroutine arraySub
   use arrayMod

   write(*,*) 'Inside arraySub()'
   allocate(theArray(3,2))
end subroutine arraySub
1
GPSmaster