przekazywanie przydzielonej tablicy z podprogramu do programu głównego w Fortranie; zastosowanie czy moduł? berło?

Aug 16 2020

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

2 francescalus Aug 16 2020 at 17:19

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ł subsz procedurą modułową makef; zewnętrzny podprogram makef.

Program główny korzysta z modułu subsi jego procedury makef, więc w programie głównym odniesienie makefdo procedury modułu, a nie do procedury zewnętrznej makef.

Podprogram modułu makefma argument, fktó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.

VladimirF Aug 16 2020 at 13:07

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.