ผ่านอาร์เรย์ที่จัดสรรจากรูทีนย่อยไปยังโปรแกรมหลักใน Fortran ใช้หรือโมดูล? อินเตอร์เฟซ?
ฉันต้องการจัดสรรอาร์เรย์ในรูทีนย่อยจากนั้นใช้อาร์เรย์นี้ในโปรแกรมหลักและส่งต่อไปยังรูทีนย่อยอื่น ๆ ในอดีต (F77?) การส่งผ่านสามารถทำได้ในบล็อกทั่วไป แต่ในปัจจุบันขั้นตอนที่ได้รับความนิยมดูเหมือนจะใช้โมดูล เมื่อฉันลองสิ่งนี้ดังตัวอย่างโค้ดคอมไพเลอร์บอกฉัน
Rank mismatch in argument ‘f’ at (1) (scalar and rank-1)
เห็นได้ชัดว่าโปรแกรมหลักคิดว่า 'f' เป็นสเกลาร์: แต่ฉันอ่านรหัสนี้หมายความว่าฉันได้ประกาศว่าเป็นอาร์เรย์หนึ่งมิติทั้งในรูทีนย่อยและในโปรแกรมหลัก ฉันขาดอะไรไป?
ฉันได้ลองใช้รูปแบบต่างๆเช่นการประกาศตัวแปรเป็นส่วนหนึ่งของโมดูล แต่ไม่มีสิ่งใดที่ฉันคิดได้ว่าการคอมไพล์นั้นปราศจากข้อผิดพลาด (และบางอันก็ทำให้เกิดข้อผิดพลาดอีกมากมาย ;-() ขอขอบคุณข้อมูลเชิงลึกใด ๆ
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
คำตอบ
โมดูลใน Fortran ไม่เหมือนกับไฟล์ส่วนหัวในภาษาอื่นซึ่งเป็นเพียงข้อมูลเกี่ยวกับสิ่งที่กำหนดไว้ที่อื่น มีแนวคิดของ "นิยามรอการตัดบัญชี" (โมดูลย่อย) แต่ในกรณีนี้โมดูลควรพูดทุกอย่างเกี่ยวกับรูทีนย่อยไม่ใช่เพียงแค่พยายามชี้ไปที่การมีอยู่ของมัน
ในตัวอย่างของคำถามเรามี: โปรแกรมหลัก; โมดูลsubs
กับขั้นตอนโมดูลmakef
; makef
ย่อยภายนอก
โปรแกรมหลักที่ใช้โมดูลsubs
และขั้นตอนของมันmakef
ดังนั้นการอ้างอิงในโปรแกรมหลักที่จะเป็นขั้นตอนโมดูลที่ไม่ย่อยภายนอกmakef
makef
รูทีนย่อยโมดูลmakef
มีอาร์กิวเมนต์f
ที่ไม่มีคำสั่งการประกาศทำให้เป็นฟังก์ชันสเกลาร์ / ภายนอกที่ประกาศโดยปริยาย นี่คือข้อความของคอมไพเลอร์ ใช้implicit noneในโมดูลเช่นเดียวกับในโปรแกรมหลักและรูทีนย่อยภายนอกที่นี่
คำจำกัดความทั้งหมดของรูทีนย่อยควรอยู่ในโมดูล:
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
หรือหากต้องการอ้างถึงการนำโพรซีเดอร์ภายนอกไปใช้ในภายหลังบล็อกอินเทอร์เฟซสามารถมีคุณลักษณะในโมดูลโดยไม่ต้องประกาศรูทีนย่อย ในกรณีนี้จำเป็นต้องระบุอินเทอร์เฟซที่สมบูรณ์:
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
ในกรณีนี้ไม่ต้องการบล็อกอินเทอร์เฟซ
คุณวางสำเนาของบรรทัดแรกและบรรทัดสุดท้ายลงในโมดูลเท่านั้น ที่ไม่สามารถทำงานได้ คุณต้องย้ายรูทีนย่อยทั้งหมดลงในโมดูล