passare l'array allocato dalla subroutine al programma principale in fortran; uso o modulo? interfaccia?
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
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 subs
con procedura modulo makef
; una subroutine esterna makef
.
Il programma principale utilizza il modulo subs
e 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 makef
ha l'argomento f
che 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.
Hai inserito solo la copia della prima e dell'ultima riga nel modulo. Non può funzionare. È necessario spostare l'intera subroutine nel modulo.