passer le tableau alloué du sous-programme au programme principal dans fortran; utiliser ou module? interface?
Je veux allouer un tableau dans un sous-programme, puis utiliser ce tableau dans le programme principal et le transmettre à un autre sous-programme. Dans le passé (F77?) Le passage pouvait se faire dans un bloc commun, mais de nos jours, la procédure préférée semble être d'utiliser un module. Quand j'essaye ceci, comme dans l'exemple de code, le compilateur me dit
Rank mismatch in argument ‘f’ at (1) (scalar and rank-1)
Apparemment, le programme principal pense que «f» est un scalaire: mais, j'ai lu ce code pour signifier que je l'ai déclaré comme un tableau unidimensionnel, à la fois dans le sous-programme et dans le programme principal. Qu'est-ce que je rate?
J'ai essayé des variantes, telles que la déclaration des variables dans le cadre du module, mais rien à quoi je pourrais penser n'a rendu la compilation sans erreur (et certaines ont produit beaucoup plus d'erreurs ;-().
module subs
contains
subroutine makef(f)
end subroutine makef
end module subs
c-----------------------------------------------------------------------
program work
use subs
implicit none
real, allocatable :: f(:)
call makef(f)
write (*,*) f
stop
end
c---------------------------------------------------------------------
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
return
end subroutine makef
Réponses
Les modules de Fortran ne sont pas comme des fichiers d'en-tête dans d'autres langages qui fournissent simplement des informations sur des éléments définis ailleurs. Il y a le concept de «définition différée» (sous-modules) mais dans ce cas, le module devrait tout dire sur le sous-programme, pas simplement tenter d'indiquer son existence.
Dans l'exemple de la question, nous avons: le programme principal; un module subs
avec procédure de module makef
; un sous-programme externe makef
.
Le programme principal utilise le module subs
et sa procédure makef
, donc la référence dans le programme principal makef
est à cette procédure de module et non au sous-programme externe makef
.
Le sous-programme du module makef
a l'argument f
qui n'a pas d'instructions de déclaration, ce qui en fait une fonction scalaire / externe implicitement déclarée. C'est le message du compilateur. Utilisez implicit nonedans les modules, tout comme c'est dans le programme principal et le sous-programme externe ici.
La définition complète du sous-programme doit être placée dans le module:
module subs
implicit none
contains
subroutine makef(f)
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
end subroutine makef
end module subs
Alternativement, si l'on veut se référer à l'implémentation ultérieure d'une procédure externe, un bloc d'interface peut figurer dans le module sans déclarer le sous-programme lui-même. Dans ce cas, il sera encore nécessaire de spécifier l'interface complète:
module subs
implicit none
! An interface block to give an explicit interface to the external subroutine makef
interface
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
end subroutine makef
end interface
end module subs
Dans ce cas, ne préférez pas le bloc d'interface.
Vous avez uniquement placé la copie de la première et de la dernière ligne dans le module. Ça ne peut pas marcher. Vous devez déplacer l'ensemble du sous-programme dans le module.