Übergeben des zugewiesenen Arrays von der Unterroutine an das Hauptprogramm in fortran; verwenden oder Modul? Schnittstelle?
Ich möchte ein Array in einer Unterroutine zuweisen und dieses Array dann im Hauptprogramm verwenden und an eine andere Unterroutine übergeben. In der Vergangenheit (F77?) Konnte die Übergabe in einem gemeinsamen Block erfolgen, aber heutzutage scheint das bevorzugte Verfahren darin zu bestehen, ein Modul zu verwenden. Wenn ich dies versuche, wie im Codebeispiel, sagt mir der Compiler
Rank mismatch in argument ‘f’ at (1) (scalar and rank-1)
Anscheinend denkt das Hauptprogramm, dass 'f' ein Skalar ist. Aber ich habe diesen Code gelesen, um zu bedeuten, dass ich ihn als eindimensionales Array deklariert habe, sowohl innerhalb des Unterprogramms als auch im Hauptprogramm. Was vermisse ich?
Ich habe Variationen ausprobiert, z. B. das Deklarieren der Variablen als Teil des Moduls, aber nichts, was mir einfiel, machte die Kompilierung fehlerfrei (und einige verursachten viel mehr Fehler ;-(). Jeder Einblick wird am meisten geschätzt.
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
Antworten
Module in Fortran sind nicht wie Header-Dateien in anderen Sprachen, die lediglich Informationen zu an anderer Stelle definierten Dingen enthalten. Es gibt das Konzept der "verzögerten Definition" (Submodule), aber in diesem Fall sollte das Modul alles über die Subroutine sagen und nicht einfach versuchen, auf ihre Existenz hinzuweisen.
Im Beispiel der Frage haben wir: das Hauptprogramm; ein Modul subs
mit Modulprozedur makef
; eine externe Unterroutine makef
.
Das Hauptprogramm verwendet das Modul subs
und seine Prozedur makef
, daher verweist im Hauptprogramm makef
auf diese Modulprozedur und nicht auf die externe Unterroutine makef
.
Das Modul-Unterprogramm makef
enthält das Argument, f
das keine Deklarationsanweisungen enthält, was es zu einer implizit deklarierten skalaren / externen Funktion macht. Dies ist die Nachricht des Compilers. Verwendung implicit nonein Modulen, genau wie im Hauptprogramm und in der externen Unterroutine hier.
Die gesamte Definition des Unterprogramms sollte in das Modul eingefügt werden:
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
Wenn man sich alternativ auf die spätere Implementierung einer externen Prozedur beziehen möchte, kann ein Schnittstellenblock im Modul enthalten sein, ohne das Unterprogramm selbst zu deklarieren. In diesem Fall muss weiterhin die vollständige Schnittstelle angegeben werden:
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 diesem Fall bevorzugen Sie nicht den Schnittstellenblock.
Sie haben nur die Kopie der ersten und der letzten Zeile in das Modul eingefügt. Das kann nicht funktionieren. Sie müssen das gesamte Unterprogramm in das Modul verschieben.