3

これは、3*3 の線形方程式を解いて結果を出力しようとしていますが、コメント行で問題が発生しました。

モジュール LinearSolution をプログラムの外部で定義しましたが、内部で定義する必要がありますか? 違いは何ですか?

ステートメントが再帰的であると言われる理由は、これらのステートメントをモジュール サブルーチンの代わりに通常のサブルーチンとして使用すると、問題がないことが確認されるからです。

module LinearSolution
    type LAE
        integer::N
        double precision,dimension(:,:),allocatable::A
        double precision,dimension(  :),allocatable::B
    contains
        procedure,nopass::RowReduction
    end type LAE
contains
    subroutine RowReduction
        double precision::C
        do k=1,N
            do i=k+1,N
                if(A(k,k)/=0) then
                    C=A(i,k)/A(k,k)
                    B(i)=B(i)-B(k)*C       !error: Statement Function is recursive
                    do j=k+1,N
                        A(i,j)=A(i,j)-A(k,j)*C   !error: Statement Function is recursive
                    end do
                end if
            end do
        end do

        do k=N,1,-1
            do i=k-1,1,-1
                if(A(k,k)/=0) then
                    C=A(i,k)/A(k,k)
                    B(i)=B(i)-B(k)*C  !error: Statement Function is recursive
                end if
            end do
        end do

        do k=1,N
            if(A(k,k)/=0) then
                B(k)=B(k)/A(k,k)  !error: Statement Function is recursive
            end if
        end do
    end subroutine RowReduction
end module LinearSolution

program TestLAE
    use LinearSolution  !fatal error: cant open module file LinearSolution.mod for reading
    type(LAE)::LAE1
    LAE1%N=3
    allocate(LAE1%B(1:N))
    allocate(LAE1%A(1:N,1:N))
    LAE1%B=(/1,1,1/)
    LAE1%A=(/2,0,0,0,2,0,0,0,2/)
    call LAE1%RowReduction
    print*, LAE1%B(1),LAE1%B(2),LAE1%B(3)
end program
4

1 に答える 1

5

よくあることimplicit noneですが、あなたの友達です。

エラーを 1 つずつ見てみましょう。

B(i)=B(i)-B(k)*C       !error: Statement Function is recursive

Bコンパイラはこのコンテキストを認識しません。ここでは変数が宣言されていないBので (*)、できることは、それがB を I の関数として定義する実数値のステートメント関数であると想定することです。再帰的にできないその他のもの。ここでは、どれが明らかに失敗するかB(i)という観点から定義しています。B(i)

(*) しかし!あなたは泣いている。 B私のタイプの配列フィールドLAEです!はい。ただし、ここでは LAE のコンテキストではありません。LAE実際、この関数のコンテキストでは、B 値を使用するタイプの変数さえありません。これは、プロシージャーが定義されているためnopassです。LAEこれらのフィールドにアクセスできるように、クラスの操作対象のオブジェクトである変数が必要です。それは次のようになります。

    type LAE
        !...
    contains
        procedure::RowReduction
    end type LAE

contains
    subroutine RowReduction(self)
        class(LAE), intent(InOut) :: self
        double precision::C
        integer :: i, j, k
        do k= 1, self%N
            do i= k+1, self%N
                if( self%A(k,k) /= 0 ) then
        !....

class(LAE)self をtype ではなくof と定義する必要があることに注意してください。class は type のスーパーセットであり、(再) 割り当て可能なコンポーネントを含む拡張可能なオブジェクトを扱うときに必要です。定義されていないことをすぐに知らせる暗黙的な none を追加したことにも注意してください。Bしたがって、整数インデックス i、j、および k を指定します。

NA、およびBが のフィールドとして正しく参照されるとself、プログラムの残りのほとんどが正しくなります。配列にする必要があることに注意してreshapeください。LAE1%A

LAE1%A=reshape((/2,0,0,0,2,0,0,0,2/), (/N, N/))

しかし、それ以外は問題ないようです。

module LinearSolution
implicit none

    type LAE
        integer::N
        double precision,dimension(:,:),allocatable::A
        double precision,dimension(  :),allocatable::B
    contains
        procedure::RowReduction
    end type LAE

contains
    subroutine RowReduction(self)
        class(LAE), intent(InOut) :: self
        double precision::C
        integer :: i, j, k
        do k= 1, self%N
            do i= k+1, self%N
                if( self%A(k,k) /= 0 ) then
                    C = self%A(i,k) / self%A(k,k)
                    self%B(i) = self%B(i)- self%B(k)*C
                    do j=k+1, self%N
                         self%A(i,j) = self%A(i,j) - self%A(k,j)*C
                    end do
                end if
            end do
        end do

        do k = self%N,1,-1
            do i=k-1,1,-1
                if( self%A(k,k)/=0) then
                    C= self%A(i,k)/ self%A(k,k)
                    self%B(i)= self%B(i)- self%B(k)*C
                end if
            end do
        end do

        do k=1, self%N
            if( self%A(k,k)/=0 ) then
                self%B(k) = self%B(k) / self%A(k,k)
            end if
        end do
    end subroutine RowReduction
end module LinearSolution

program TestLAE
    use LinearSolution
    implicit none

    integer, parameter :: N = 3
    type(LAE)::LAE1
    LAE1%N=N
    allocate(LAE1%B(1:N))
    allocate(LAE1%A(1:N,1:N))
    LAE1%B=(/1,1,1/)
    LAE1%A=reshape((/2,0,0,0,2,0,0,0,2/), (/N, N/))
    call LAE1%RowReduction
    print*, LAE1%B(1),LAE1%B(2),LAE1%B(3)
end program

実行すると次のようになります。

$ gfortran -o lae lae.f90 -Wall -std=f2003
$ ./lae
  0.50000000000000000       0.50000000000000000       0.50000000000000000     
于 2012-12-29T04:12:24.447 に答える