簡體   English   中英

如何將許多臨時數組傳遞給 Fortran 中的子程序?

[英]How to pass many temporary arrays to a subroutine in Fortran?

假設我正在編寫一個 Fortran 子程序,它執行模擬的一個時間步長,因此將被重復調用。 為了完成它的工作,它需要許多臨時數組,這些數組在子例程之外沒有意義或有用。 用戶可能希望在程序執行期間執行多個不同大小的模擬,可能同時進行,但對於特定模擬的所有時間步長,數組的維度將相同。

我應該如何處理這些臨時數組? 我能想到的每一種方式都有問題。

  • 如果我要使用子例程本地的數組,它們要么必須放在堆棧上,這將限制它們的大小,要么必須在堆上分配它們,這會浪費時間,因為數組會分配和解除分配每個時間步。

  • 或者,調用者可以分配數組。 但是,如果調用者要將每個數組作為單獨的參數傳遞給子例程,則調用者必須知道有多少個數組以及每個數組有多大。 此外,如果以某種方式修改了子例程,從而改變了數組的數量或大小,則必須修改對子例程的每次調用。

  • 我見過的一種技術是讓子例程接受單個大數組並將其視為幾個連接在一起的臨時數組。 然而,這似乎有風險,因為算術錯誤可能導致難以發現的錯誤。

  • 最后,我可以將所有臨時數組放入派生類型並編寫一個單獨的子例程來分配所有數組和另一個子例程來釋放它們。 這樣,只有少數子程序必須知道臨時數組。 但是,我的理解是,至少在 Fortran 的最新版本之前,派生類型只能包含指向數組的指針。 這會帶來與使用指針相關的所有缺點(潛在的錯誤、別名等)。

有沒有辦法避免這些問題? (或者這些問題中的任何一個都沒有我想象的那么重要?)

您可以在數組上使用 save 屬性。

subroutine step(x, t, do_allocattion)
    double precision, intent(in) :: x(:)
    double precision, intent(in) :: t
    logical, intent(in), optional :: do_allocation

    integer :: n
    double precision, allocatable, save :: work1(:), work2(:)
    n = size(x)

    if (present(do_allocation)) then
        if (do_allocation) then
            allocate(work1(n))
            allocate(work2(n))
        end if
    end if

    ! do work on x
end subroutine

編輯:替代解決方案,因為我與指針數組混淆了。

subroutine step(x, t)
    double precision, intent(in) :: x(:)
    double precision, intent(in) :: t

    integer :: n
    double precision, allocatable, save :: work1(:), work2(:)
    n = size(x)

    if (.not. allocated(work1)) then
        allocate(work1(n))
    end if
    if (.not. allocated(work2)) then
        allocate(work2(n))
    end if

    ! do work on x
end subroutine

編輯:注意:您不能簡單地檢查“分配”,因為它在程序啟動和子程序第一次執行時是未定義的。 您可以添加另一個可選參數來解除分配。 -> 指針數組就是這種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM