melewatkan array yang dialokasikan dari subrutin ke program utama di fortran; gunakan atau modul? antarmuka?
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
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 subs
dengan prosedur modul makef
; subrutin eksternal makef
.
Program utama menggunakan modul subs
beserta prosedurnya makef
, sehingga acuan dalam program utama makef
adalah prosedur modul tersebut bukan subrutin eksternal makef
.
Subrutin modul makef
memiliki argumen f
yang 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.
Anda hanya menempatkan salinan baris pertama dan terakhir ke dalam modul. Itu tidak bisa. Anda harus memindahkan seluruh subrutin ke dalam modul.