melewatkan array yang dialokasikan dari subrutin ke program utama di fortran; gunakan atau modul? antarmuka?

Aug 16 2020

Saya ingin mengalokasikan array dalam subrutin, dan kemudian menggunakan array ini dalam program utama dan meneruskannya ke subrutin lain. Dulu (F77?) Passing bisa dilakukan di blok yang sama, tapi sekarang prosedur yang disukai tampaknya menggunakan modul. Ketika saya mencoba ini, seperti pada contoh kode, kompilator memberitahu saya

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

Rupanya, program utama mengira bahwa 'f' adalah skalar: tetapi, saya membaca kode ini yang berarti bahwa saya telah menyatakannya sebagai larik satu dimensi, baik di dalam subrutin maupun di program utama. Apa yang saya lewatkan?

Saya telah mencoba variasi, seperti mendeklarasikan variabel sebagai bagian dari modul, tetapi tidak ada yang terpikir untuk membuat kompilasi ini bebas dari kesalahan (dan beberapa menghasilkan lebih banyak kesalahan ;-(). Setiap wawasan sangat dihargai.

          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

Jawaban

2 francescalus Aug 16 2020 at 17:19

Modul di Fortran tidak seperti file header dalam bahasa lain yang hanya memberikan informasi tentang hal-hal yang didefinisikan di tempat lain. Ada konsep "deferred definition" (submodul) tetapi dalam hal ini modul harus menjelaskan segala sesuatu tentang subrutin, bukan sekadar berusaha menunjukkan keberadaannya.

Dalam contoh pertanyaan, kami memiliki: program utama; modul subsdengan prosedur modul makef; subrutin eksternal makef.

Program utama menggunakan modul subsbeserta prosedurnya makef, sehingga acuan dalam program utama makefadalah prosedur modul tersebut bukan subrutin eksternal makef.

Subrutin modul makefmemiliki argumen fyang tidak memiliki pernyataan deklarasi, menjadikannya fungsi skalar / eksternal yang dideklarasikan secara implisit. Ini adalah pesan penyusun. Gunakan implicit nonedi modul, seperti di program utama dan subrutin eksternal di sini.

Seluruh definisi subrutin harus ditempatkan di modul:

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

Alternatifnya, jika seseorang ingin merujuk ke implementasi selanjutnya dari prosedur eksternal, blok antarmuka dapat ditampilkan dalam modul tanpa mendeklarasikan subrutin itu sendiri. Dalam kasus ini, masih perlu untuk menentukan antarmuka lengkap:

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

Dalam kasus ini, jangan suka blok antarmuka.

VladimirF Aug 16 2020 at 13:07

Anda hanya menempatkan salinan baris pertama dan terakhir ke dalam modul. Itu tidak bisa. Anda harus memindahkan seluruh subrutin ke dalam modul.