2017-10-09 2 views
1

J'ai du mal à comprendre les interfaces Fortran. Le code de code de test collé à la fin de la question compile très bien sur ifort < = version 15, mais provoque une erreur de compilation catastrophique sur les versions 16 et supérieures. Idem sur gfortran (erreur de segmentation lors de la compilation). Le G95, cependant, la compilation se termine par l'erreur suivanteInterfaces ne correspondant pas à 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) 

mais je ne suis pas sûr de ce que je fais mal ...

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

Bienvenue. Assurez-vous de prendre l'accueil [tour]. Utilisez tag [tag: fortran] pour toutes les questions Fortran. Vous pouvez ajouter une balise de version spécifique pour une question spécifique à une version, mais notez que Fortran 90 est une version ancienne et obsolète et que vous ne voulez généralement pas être limité à cela. –

+0

Les plaidoyers utilisent une indentation (espaces au début de chaque ligne). Votre code est très difficile à lire. Nous ne pouvons pas voir la structure. –

+2

Et OMG arrêter d'utiliser la fonctionnalité de retour alternatif (https: // stackoverflow.com/questions/7835270/astérisques-dans-fortran-syntax-error-in-argument-list-at-1) en ce moment, c'est un chemin vers l'enfer, croyez-nous. –

Répondre

1

Le code fonctionne très bien dans la version gfortran 6 et 7.

Gfortran version 4.8 se bloque, mais c'est le problème du compilateur. Un compilateur ne devrait jamais tomber en panne, même si le code est mauvais.

La même chose vaut pour Intel Fortran. S'il tombe en panne lors de la compilation, c'est la faute du compilateur.

Maintenant, le code n'est vraiment pas génial et utilise des fonctionnalités qui peuvent être difficiles pour le compilateur. En ce qui concerne les choses par rapport aux normes, gfortran 6 se plaint de:

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) 

Il est interdit en Fortran passer la même variable aux arguments de cette façon. Le compilateur supposera que l'argument intent(in) ne change jamais, mais il change lorsque vous modifiez yout. Cela peut causer de sérieux problèmes.

Pour l'erreur de temps de compilation G95, je pense que le compilateur est faux et le message d'erreur est faux. Les blocs d'interface dans rk4 et adaptive_rk4 sont exactement les mêmes.

Je vous conseille fortement de nettoyer le code, de vous débarrasser de la fonctionnalité de sortie alternative et il sera beaucoup plus facile pour les compilateurs de compiler le code. Je suppose que c'est dû à votre utilisation excessive de la fonctionnalité de retour alternatif qui n'est pas testé trop.


Pour vos prochaines questions, lisez très attentivement [mcve]. Il est nécessaire de faire votre code beaucoup plus court pour vos futures questions. C'est la réelle MCVE vous devriez demander et qui peut être utilisé comme base pour un rapport de bogue:

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 

Comparez avec le nous a fait don très long code. Cela ne peut plus vraiment être réduit sans que le crash du compilateur disparaisse (à la fois ifort 17 et gcc 4.8). Le problème est clairement dans la procédure factice (même si elle n'est appelée nulle part), qui utilise la fonctionnalité de retour alternatif et le compilateur ne peut pas le traiter correctement.

+0

merci! Je n'avais pas remarqué le problème avec l'attribut intention (out), qui explique en rétrospective d'autres choses étranges qui se passaient à cette même ligne quand le code était en train de compiler. Et désolé pour les fonctionnalités obsolètes/code long, je me souviendrai à l'avenir –

0

J'ai remplacé les retours alternatifs des instances de DERR/DER et ensuite la compilation a fonctionné dans Intel Fortran (XE 2017). Je suis également d'accord qu'il est conseillé de (1) nettoyer le code et (2) éviter l'utilisation de retours alternatifs.