passare l'array allocato dalla subroutine al programma principale in fortran; uso o modulo? interfaccia?

Aug 16 2020

Voglio allocare un array in una subroutine, quindi utilizzare questo array nel programma principale e passarlo a qualche altra subroutine. In passato (F77?) Il passaggio poteva essere fatto in un blocco comune, ma oggi la procedura preferita sembra essere quella di utilizzare un modulo. Quando provo questo, come nell'esempio di codice, il compilatore me lo dice

Rank mismatch in argument ‘f’ at (1) (scalar and rank-1)

Apparentemente, il programma principale pensa che 'f' sia uno scalare: ma, ho letto questo codice per significare che l'ho dichiarato come un array unidimensionale, sia all'interno della subroutine che nel programma principale. Cosa mi manca?

Ho provato varianti, come dichiarare le variabili come parte del modulo, ma niente a cui potevo pensare ha reso la compilazione priva di errori (e alcuni hanno prodotto molti più errori ;-(). Qualsiasi intuizione è molto apprezzata.

          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

Risposte

2 francescalus Aug 16 2020 at 17:19

I moduli in Fortran non sono come i file di intestazione in altre lingue che forniscono semplicemente informazioni su cose definite altrove. Esiste il concetto di "definizione differita" (sottomoduli) ma in questo caso il modulo dovrebbe dire tutto sulla subroutine, non semplicemente tentare di indicarne l'esistenza.

Nell'esempio della domanda, abbiamo: il programma principale; un modulo subscon procedura modulo makef; una subroutine esterna makef.

Il programma principale utilizza il modulo subse la sua procedura makef, quindi il riferimento nel programma principale makefè a quella procedura del modulo, non alla subroutine esterna makef.

La subroutine del modulo makefha l'argomento fche non ha dichiarazioni di dichiarazione, rendendola una funzione scalare / esterna implicitamente dichiarata. Questo è il messaggio del compilatore. Utilizzare implicit nonenei moduli, proprio come nel programma principale e nella subroutine esterna qui.

L'intera definizione della subroutine dovrebbe essere inserita nel modulo:

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

In alternativa, se si vuole fare riferimento alla successiva implementazione di una procedura esterna, un blocco di interfaccia può essere presente nel modulo senza dichiarare la subroutine stessa. In questo caso sarà comunque necessario specificare l'interfaccia completa:

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

In questo caso, non preferire il blocco dell'interfaccia.

VladimirF Aug 16 2020 at 13:07

Hai inserito solo la copia della prima e dell'ultima riga nel modulo. Non può funzionare. È necessario spostare l'intera subroutine nel modulo.