przekazywanie przydzielonej tablicy z podprogramu do programu głównego w Fortranie; zastosowanie czy moduł? berło?
Chcę przydzielić tablicę w podprogramie, a następnie użyć tej tablicy w głównym programie i przekazać ją do innego podprogramu. W przeszłości (F77?) Przekazywanie mogło odbywać się we wspólnym bloku, ale obecnie preferowaną procedurą wydaje się być użycie modułu. Kiedy próbuję tego, jak w przykładzie kodu, kompilator mi powie
Rank mismatch in argument ‘f’ at (1) (scalar and rank-1)
Najwyraźniej główny program myśli, że „f” jest skalarem, ale czytam ten kod, aby oznaczać, że zadeklarowałem go jako jednowymiarową tablicę, zarówno wewnątrz procedury, jak i w programie głównym. czego mi brakuje?
Próbowałem różnych odmian, takich jak zadeklarowanie zmiennych jako część modułu, ale nic, co przychodziło mi do głowy, nie powodowało, że kompilacja była wolna od błędów (a niektóre powodowały o wiele więcej błędów ;-(). Wszelkie spostrzeżenia są bardzo mile widziane.
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
Odpowiedzi
Moduły w Fortranie nie są jak pliki nagłówkowe w innych językach, które jedynie dostarczają informacji o rzeczach zdefiniowanych gdzie indziej. Istnieje pojęcie „odroczonej definicji” (submodułów), ale w tym przypadku moduł powinien mówić wszystko o podprogramie, a nie tylko próbować wskazywać na jego istnienie.
W przykładzie pytania mamy: program główny; moduł subs
z procedurą modułową makef
; zewnętrzny podprogram makef
.
Program główny korzysta z modułu subs
i jego procedury makef
, więc w programie głównym odniesienie makef
do procedury modułu, a nie do procedury zewnętrznej makef
.
Podprogram modułu makef
ma argument, f
który nie zawiera deklaracji, co czyni go niejawnie zadeklarowaną funkcją skalarną / zewnętrzną. To jest wiadomość kompilatora. Używaj implicit nonew modułach, tak jak w głównym programie i zewnętrznym podprogramie tutaj.
Całą definicję podprogramu należy umieścić w 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
Alternatywnie, jeśli ktoś chce odnieść się do późniejszej implementacji procedury zewnętrznej, blok interfejsu może znajdować się w module bez deklarowania samego podprogramu. W takim przypadku nadal konieczne będzie określenie całego interfejsu:
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
W takim przypadku nie preferuj bloku interfejsu.
Umieściłeś tylko kopię pierwszej i ostatniej linii w module. To nie może zadziałać. Musisz przenieść cały podprogram do modułu.