2017-10-09 104 views
1

我很難理解Fortran接口。在問題結尾處粘貼的測試代碼代碼在ifort < =版本15上編譯得很好,但在版本16和更高版本上會導致災難性編譯器錯誤。同樣gfortran(編譯時出現seg fault)。在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:fortran]。您可以爲特定於版本的問題添加特定的版本標籤,但請注意,Fortran 90是舊的和過時的版本,通常您不希望受限於此。 –

+0

請使用一些縮進(每行開始處的空格)。你的代碼很難閱讀。我們看不到結構。 –

+2

而OMG停止使用備用返回功能(https:// stackoverflow。com/questions/7835270/asterisks-in-fortran-syntax-in-argument-list-at-1)現在,這是一種下地獄,相信我們的方式。 –

回答

1

的代碼運行在gfortran版本6和7

罰款

Gfortran版本4.8崩潰,但這是編譯器的問題。即使代碼不好,編譯器也不應該崩潰。

對於英特爾Fortran也是如此。如果在編譯過程中崩潰,則是編譯器的錯誤。

現在,代碼真的不是很好,並且使用編譯器可能很難的功能。當涉及到對標準的東西,gfortran 6抱怨的:

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) 

它不是用Fortran允許通過相同的變量中的參數以這種方式。編譯器將假定intent(in)參數不會更改,但在修改yout時確實會更改。這可能會導致嚴重的問題。

對於G95編譯時錯誤,我認爲編譯器是錯誤的,錯誤信息是假的。 rk4adaptive_rk4中的接口塊完全相同。

我強烈建議您清理代碼,擺脫備用退出功能,編譯器編譯代碼會更容易。我預計這是由於您過度使用未經太多測試的備用返回功能。


你的下一個問題,肯定讀[MCVE]非常謹慎。有必要使您的代碼短得多爲您的未來的問題。這是實際MCVE你應該詢問,並可以作爲一個bug報告基地:

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

謝謝!我沒有注意到intent(out)屬性的問題,後者在代碼編譯時確實發生了一些奇怪的事情。對於過時的功能/長代碼抱歉,我將來會記得 –

0

我從DERR/DER實例中替換了備用返回,然後編譯在英特爾Fortran(XE 2017)中運行。 我同意,建議(1)清理代碼並(2)避免使用替代退貨。