passer le tableau alloué du sous-programme au programme principal dans fortran; utiliser ou module? interface?

Aug 16 2020

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

2 francescalus Aug 16 2020 at 17:19

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 subsavec procédure de module makef; un sous-programme externe makef.

Le programme principal utilise le module subset sa procédure makef, donc la référence dans le programme principal makefest à cette procédure de module et non au sous-programme externe makef.

Le sous-programme du module makefa l'argument fqui 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.

VladimirF Aug 16 2020 at 13:07

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.