2017-10-09 17 views
1

Fortranインターフェイスを理解するのに苦労しています。問題の最後に貼り付けられたテストコードコードは、ifort < =バージョン15で正常にコンパイルされますが、バージョン16以降では致命的なコンパイラエラーが発生します。 gfortran(コンパイル中のsegフォルト)と同じです。 G95には、しかし、コンパイルは次のエラーFortran 90で一致しないインターフェイス

In file test.f90:79 

call rk4(y, dydx, x, h, yout1, der, pars,*10) 
           1 
Error: Interface of actual procedure does not match interface of dummy procedure at (1) 
In file test.f90:81 

call rk4(y, dydx, x, h/2.d0, yout2, der, pars,*10) 
            1 
Error: Interface of actual procedure does not match interface of dummy procedure at (1) 
In file test.f90:85 

call rk4(yout2, dydx2, x+h/2.d0, h/2.d0, yout2, der, pars,*10) 
               1 
Error: Interface of actual procedure does not match interface of dummy procedure at (1) 

で終わるが、私は私が間違っているのかわからないよ...

module RK 

implicit none 

contains 

SUBROUTINE rk4(y, dydx, x, h, yout, der, pars, *) 
IMPLICIT NONE 
integer, parameter :: dp=kind(1.d0) 
REAL(dp), DIMENSION(:), INTENT(IN) :: y,dydx,pars 
REAL(dp), INTENT(IN) :: x,h 
REAL(dp), DIMENSION(:), INTENT(OUT) :: yout 
REAL(dp) :: h6,hh,xh 
REAL(dp), DIMENSION(size(y)) :: dym,dyt,yt 

INTERFACE 
SUBROUTINE der(x,y,dydx,pars,*) 
IMPLICIT NONE 
integer, parameter :: dp=kind(1.d0) 
REAL(dp), INTENT(IN) :: x 
REAL(dp), DIMENSION(:), INTENT(IN) :: pars 
REAL(dp), DIMENSION(:), INTENT(IN) :: y 
REAL(dp), DIMENSION(:), INTENT(OUT) :: dydx 
END SUBROUTINE der 
END INTERFACE 


hh = h*0.5d0 
h6 = h/6.d0 
xh = x + hh 

yt(:)=y(:)+hh*dydx(:) 

call der(xh, yt, dyt, pars,*10) 

yt(:)=y(:)+hh*dyt(:) 

call der(xh, yt, dym, pars,*10) 

yt(:)=y(:)+h*dym(:) 

dym(:)=dyt(:)+dym(:) 

call der(x+h, yt, dyt, pars,*10) 

yout(:)=y(:)+h6*(dydx(:)+dyt(:)+2.d0*dym(:)) 

return 
10 return 1 


end subroutine 


subroutine adaptive_RK4(y,dydx,x,h,yout2,yerr,der,pars,*) 
implicit none 
integer, parameter :: dp=kind(1.d0) 
REAL (dp) :: h, x 
REAL (dp), DIMENSION (:) :: y, dydx, yout2, yerr, pars 
REAL (dp), DIMENSION (size(y)) :: dydx2, yout1 
intent(in) :: y, dydx, x, h, pars 
intent(out) :: yout2, yerr 
INTERFACE 
SUBROUTINE der(x,y,dydx,pars,*) 
IMPLICIT NONE 
integer, parameter :: dp=kind(1.d0) 
REAL(dp), INTENT(IN) :: x 
REAL(dp), DIMENSION(:), INTENT(IN) :: pars 
REAL(dp), DIMENSION(:), INTENT(IN) :: y 
REAL(dp), DIMENSION(:), INTENT(OUT) :: dydx 
END SUBROUTINE der 
END INTERFACE 


call rk4(y, dydx, x, h, yout1, der, pars,*10) 

call rk4(y, dydx, x, h/2.d0, yout2, der, pars,*10) 

call der(x+h/2.d0, yout2, dydx2, pars,*10) 

call rk4(yout2, dydx2, x+h/2.d0, h/2.d0, yout2, der, pars,*10) 

yerr(:)=yout2(:)-yout1(:) 

yout2(:)=(16.d0*yout2(:)-yout1(:))/15.d0 

return 

10 return 1 

end subroutine 

end module 

module derivative 
implicit none 
contains 
    SUBROUTINE derr(x,y,dydx,pars,*) 
    IMPLICIT NONE 
integer, parameter :: dp=kind(1.d0) 
    REAL(dp), INTENT(IN) :: x 
    REAL(dp), DIMENSION(:), INTENT(IN) :: pars 
    REAL(dp), DIMENSION(:), INTENT(IN) :: y 
    REAL(dp), DIMENSION(:), INTENT(OUT) :: dydx 


dydx=(pars+y)*x 
return 

END SUBROUTINE derr 

end module 

program test 
use rk 
use derivative 
implicit none 
integer, parameter :: dp=kind(1.d0) 
real(dp), dimension(2) :: y,pars,dydx, yout, yerr 
real(dp) :: x 

y=(/0.1d0,2.d0/) 
pars=(/0.7d0,3.d0/) 
x=2.1d0 

call derr(x,y,dydx,pars,*10) 

write(*,*) dydx 
call adaptive_RK4(y,dydx,x,0.0001d0,yout,yerr,derr,pars,*10) 

stop 
10 write(*,*) "some error" 

end program 
+0

ようこそ。歓迎[ツアー]を必ず取るようにしてください。すべてのFortranの質問には、tag [tag:fortran]を使用します。特定のバージョンの質問に特定のバージョンタグを追加することはできますが、Fortran 90は古くて古くなったバージョンであり、通常はそれに限定されたくないことに注意してください。 –

+0

いくつかのインデント(各行の先頭のスペース)を使用します。あなたのコードは読みにくいです。私たちは構造を見ることができません。 –

+2

OMGは、代替リターン機能(https:// stackoverflow。com/questions/7835270/fortran-in-fortran-syntax-in-argument-list-at-1)今は地獄への道です。 –

答えて

1

コードはのgfortranバージョン6と7

に細かい動作します

Gfortranバージョン4.8がクラッシュしますが、それはコンパイラの問題です。たとえコードが悪い場合でも、コンパイラは決してクラッシュするべきではありません。

インテルFortranでも同様です。コンパイル中にクラッシュすると、コンパイラの問題です。

今、コードは実際にはあまり良くなく、コンパイラにとっては難しい機能を使用しています。このように引数にして同じ変数を渡すようにFortranで許可されていない

interface2.f90:81:9: 

call rk4(yout2, dydx2, x+h/2.d0, h/2.d0, yout2, der, pars,*10) 
     1 
Warning: Same actual argument associated with INTENT(IN) argument ‘y’ and INTENT(OUT) argument ‘yout’ at (1) 

:それは標準に対するものになると、のgfortran 6は訴えます。コンパイラはintent(in)引数が決して変更されないと仮定しますが、youtを変更すると変更されます。これは重大な問題を引き起こします。

コンパイル時にエラーが発生した場合、コンパイラは間違っていて、エラーメッセージは偽であると思います。 rk4adaptive_rk4のインターフェイスブロックはまったく同じです。

コードをクリーンアップすることをお勧めします。代替出口機能を取り除くことを強くお勧めします。コンパイラがコードをコンパイルする方がずっと簡単です。私はそれがあまりにも多くテストされていない代替リターン機能のあなたの過度の使用によるものと期待しています。


次の質問については、[mcve]をよくお読みください。あなたのコードをもっと短くにする必要があります。 THISについて、あなたは尋ねるべきとされ、バグレポートのベースとして使用することができ、実際のMCVEです:

module m 

    implicit none 

contains 

    subroutine a(d) 
    interface 
     subroutine d(*) 
     end subroutine d 
    end interface 

    10 return 1 
    end subroutine 


    subroutine b(d) 
    interface 
     subroutine d(*) 
     end subroutine d 
    end interface 

    call a(d) 
    end subroutine 
end module 

は、あなたが私たちを与えた非常に長いコードと比較してみてください。これはコンパイラのクラッシュが消えずにもはや実際には減らすことができません(ifort 17とgcc 4.8の両方)。この問題は、代替戻り関数を使用するダミープロシージャ(実際にはどこでも呼び出されていなくても)に明らかにあり、コンパイラはそれを適切に処理できません。

+0

ありがとう!私はインテント(out)属性の問題に気づいていませんでした。これは、コードがコンパイルされているときに、その行で起こっていたいくつかの奇妙なことを後悔して説明しています。時代遅れの機能や長いコードについては残念ですが、今後は覚えています –

0

DERR/DERのインスタンスからの代替戻り値を置き換え、コンパイルはIntel Fortran(XE 2017)で機能しました。 私は、(1)コードをクリーンアップし、(2)代替リターンの使用を避けることをお勧めします。

関連する問題