2

Fortran 2003 のオブジェクト指向機能を使用しようとしていますが、問題が発生しています。まず、抽象データ型 sparse_matrix があります。

type, abstract :: sparse_matrix
    (some data)
contains
    procedure(matrix_vector_multiply), deferred :: matvec
end type sparse_matrix

abstract interface
    subroutine matrix_vector_multiply(A,x,y)
        import :: sparse_matrix
        class (sparse_matrix), intent(in) :: A
        real(kind=8), dimension(:) :: x,y
    end subroutine matrix_vector_multiply
end abstract interface

次に、sparse_matrix から継承する具体的なデータ型があります

type, extends(sparse_matrix) :: csr_sparse_matrix
    (some more data)
contains
    procedure :: matvec => csr_matvec
end type csr_sparse_matrix

そしてmatvecの実際の実装:

subroutine csr_matvec(A,x,y)
    class (csr_sparse_matrix), intent(in) :: A
    real(kind=8), dimension(:) :: x,y
    (do stuff)
end subroutine csr_matvec

後で、別のモジュールで matvec を使用したいのですが、どの動的タイプを持っているかは気にしません。

subroutine solve(A,x,b,tolerance)
    class (sparse_matrix), intent(in) :: A
    real(kind=8), dimension(:), intent(in) :: b
    real(kind=8), dimension(:), intent(out) :: x
    real(kind=8), intent(in) :: tolerance
    real(kind=8), dimension( A%nrow ) :: z

    call A%matvec(b,z)
    (more stuff)
end subroutine solver

matvec私の理解では、サブルーチンが子データ型でオーバーライドされている限り、動的型 A が何であれ、すべてが正常に機能するはずです。

このコードは問題なくコンパイルされますが、実行するとセグメント エラーが発生します。solve手順で行列の宣言を次のように変更すると、次のようになります。

     class (csr_sparse_matrix), intent(in) :: A

それはうまく動作します。同様に、 A を sparse_matrix のままにし、使用する場合

select type(A)
type is (csr_sparse_matrix)
    (the same stuff)
end select

その後、すべてが正常に実行されます。しかし、これはそもそも抽象型のプロシージャをオーバーライドするという目的全体を無効にします。プログラムは、行列とベクトルの乗算を実行できる限り、使用している行列の種類を気にする必要はありません。

とにかく、私が含めるのを忘れた属性の問題だと確信していますが、それが何であるかはわかりません.

4

1 に答える 1

2

つまり、それは結局のところコンパイラでした。私はgfortran4.6.3を使用していましたが、抽象データ型はgfortran4.7の時点でのみ適切にサポートされていました。残念ながら、いくつかのLinuxディストリビューションの長期サポートリリースにはバージョン4.6しか含まれていないため、これによりコードの移植性が低下します。

于 2013-03-14T17:58:07.913 に答える