2015-12-02 72 views
1

我有一個21x21矩陣,其中大部分是持有的。某些元素需要用離散數字進行初始化。現有的解決方案是兩步初始化:首先將所有元素設置爲1,然後將選定元素重新分配給離散數字。矩陣初始化 - 如何避免重疊?

這是在一個傳統的FORTRAN77代碼中實現的,見下文,它可以很好地與gfortran-4.9(甚至沒有警告)編譯。

但是,我需要在運行gfortran-4.4的舊服務器上編譯它。由於「重疊初始化」,這與編譯器等替代工具(如f2cg95)一起失敗。

現在,我怎樣才能重新編碼的問題,它避免了在特殊的BLOCK DATA程序單元中的這種重疊?我也認爲不建議使用英特爾Fortran編譯器,因爲初始化順序無法保證。

 SUBROUTINE TEST 
     REAL*8 MAT(21,21) 
     COMMON /PARAMETERS/ MAT 
     END 

     BLOCK DATA 
     REAL*8 MAT(21,21) 
     COMMON /PARAMETERS/ MAT 
     DATA MAT/441*1/ 
     DATA (MAT(1,J),J=2,19)/ 
    &  0.971440D0, 0.940444D0, 1, 0.994435D0, 0.708218D0, 
    &  0.931484D0, 1.170520D0, 0.990124D0, 1, 1.019530D0, 
    &  0.989844D0, 1.002350D0, 0.999248D0, 1.107274D0, 0.880880D0, 
    &  0.880973D0, 0.881047D0, 0.881141D0/ 
     DATA (MAT(2,J),J=3,14)/ 
    &  1.022740D0, 0.970120D0, 0.945939D0, 0.744954D0, 0.902271D0, 
    &  1.084320D0, 1.005710D0, 1.021000D0, 0.944914D0, 0.973384D0, 
    &  0.959340D0, 0.945520D0/ 
     DATA (MAT(3,J),J=4,19)/ 
    &  0.925053D0, 0.940237D0, 0.849408D0, 0.955052D0, 1.281790D0, 
    &  1.5D0, 1, 0.904849D0, 0.897342D0, 0.724255D0, 
    &  0.859744D0, 0.855134D0, 0.831229D0, 0.808310D0, 0.784323D0, 
    &  0.745171D0/ 
     DATA (MAT(4,J),J=5,14)/1.022540D0, 0.493148D0, 0.944871D0, 
    &  1.144440D0, 3*1, 1.013040D0, 1, 1.00532D0/ 
     DATA (MAT(5,J),J=8,12)/1.034787D0, 3*1, 1.0049D0/ 
     DATA (MAT(7,J),J=15,19)/1.008492D0, 1.010124D0, 1.011501D0, 
    &  1.012821D0, 1.014089D0/ 
     DATA (MAT(8,J),J=9,12)/1.1D0, 1, 1.3D0, 1.3D0/ 
     END 
+0

是的,您需要初始化每個「mat」元素(最多)一次。但在我看來,在隨後的'data'語句中給出的其他元素應該與'1'混合的元素的明顯答案可能並不是你所追求的。真的嗎? – francescalus

+0

只需在塊數據中執行'DATA MAT/441 * 1 /',然後將其他所有內容移動到具有可執行指定的初始化子例程。 – agentp

+0

如果我這樣做,儘管@agentp,我不會在第一個地方打擾塊數據。 [仍然是一個解決方案,說。] – francescalus

回答

2

如果「重疊初始化」是不允許的,一個簡單的方法可以是剛剛之前和之後的特定數據插入n*1並用1也填充剩餘部分,例如,

 BLOCK DATA 
     REAL*8 MAT(21,21) 
     COMMON /PARAMETERS/ MAT 
     DATA MAT(1,:)/1, 
    &  0.971440D0, 0.940444D0, 1, 0.994435D0, 0.708218D0, 
    &  0.931484D0, 1.170520D0, 0.990124D0, 1, 1.019530D0, 
    &  0.989844D0, 1.002350D0, 0.999248D0, 1.107274D0, 0.880880D0, 
    &  0.880973D0, 0.881047D0, 0.881141D0, 2*1/
     DATA MAT(2,:)/2*1, 
    &  1.022740D0, 0.970120D0, 0.945939D0, 0.744954D0, 0.902271D0, 
    &  1.084320D0, 1.005710D0, 1.021000D0, 0.944914D0, 0.973384D0, 
    &  0.959340D0, 0.945520D0, 7*1/
     DATA MAT(3,:)/3*1, 
    &  0.925053D0, 0.940237D0, 0.849408D0, 0.955052D0, 1.281790D0, 
    &  1.5D0, 1, 0.904849D0, 0.897342D0, 0.724255D0, 
    &  0.859744D0, 0.855134D0, 0.831229D0, 0.808310D0, 0.784323D0, 
    &  0.745171D0, 2*1/
     DATA MAT(4,:)/4*1, 
    &  1.022540D0, 0.493148D0, 0.944871D0, 
    &  1.144440D0, 3*1, 1.013040D0, 1, 1.00532D0, 7*1/
     DATA MAT(5,:)/7*1, 1.034787D0, 3*1, 1.0049D0, 9*1/
     DATA MAT(6,:)/21*1/
     DATA MAT(7,:)/14*1, 
    &  1.008492D0, 1.010124D0, 1.011501D0, 
    &  1.012821D0, 1.014089D0, 2*1/
     DATA MAT(8,:)/8*1, 1.1D0, 1, 1.3D0, 1.3D0, 9*1/
     DATA MAT(9:21,:)/273*1/
     END 

正如評論中所建議的,另一種方法是用陣列分配替換所有DATA語句,例如,

 SUBROUTINE init_data 
     IMPLICIT NONE 
     REAL*8 MAT(21,21), ONE 
     COMMON /PARAMETERS/ MAT 
     PARAMETER (ONE = 1.0D0) 
     INTEGER i 

     MAT(:,:) = ONE 

     MAT(1, 2:19) = [ 
    &  0.971440D0, 0.940444D0, ONE,  0.994435D0, 0.708218D0, 
    &  0.931484D0, 1.170520D0, 0.990124D0, ONE,  1.019530D0, 
    &  0.989844D0, 1.002350D0, 0.999248D0, 1.107274D0, 0.880880D0, 
    &  0.880973D0, 0.881047D0, 0.881141D0 ] 
     MAT(2, 3:14) = [ 
    &  1.022740D0, 0.970120D0, 0.945939D0, 0.744954D0, 0.902271D0, 
    &  1.084320D0, 1.005710D0, 1.021000D0, 0.944914D0, 0.973384D0, 
    &  0.959340D0, 0.945520D0 ] 
     MAT(3, 4:19) = [ 
    &  0.925053D0, 0.940237D0, 0.849408D0, 0.955052D0, 1.281790D0, 
    &  1.5D0,  ONE,  0.904849D0, 0.897342D0, 0.724255D0, 
    &  0.859744D0, 0.855134D0, 0.831229D0, 0.808310D0, 0.784323D0, 
    &  0.745171D0 ] 
     MAT(4, 5:14) = [ 1.022540D0, 0.493148D0, 0.944871D0, 
    &  1.144440D0, (ONE,i=1,3), 1.013040D0, ONE, 1.00532D0 ] 
     MAT(5, 8:12) = [ 1.034787D0, (ONE,i=1,3), 1.0049D0 ] 
     MAT(7, 15:19) = [ 1.008492D0, 1.010124D0, 1.011501D0, 
    &     1.012821D0, 1.014089D0 ] 
     MAT(8, 9:12) = [ 1.1D0, ONE, 1.3D0, 1.3D0 ] 
     END 

這似乎有點多整齊地給我。雖然我已經確認此代碼適用於gfortran 4.4.7,但可能需要使用(/.../)而不是[...]來適用於更老的編譯器,例如(/ 1.0d0, 2.0d0, ... /)。另請注意,在第二種方法中,我們需要在程序的某個點處調用init_data,與BLOCK DATA相比,在執行程序時數據會自動初始化。

+0

我同意你的觀點,但我可能建議你儘可能使這個答案爲F77-y?也就是說,固定格式的源文件,非數組語法,不需要'[','::'等等,這只是爲了儘可能減小變化,無論是否真的使用了F77編譯器。 [是的,'真實* 8'不是F77無論是...] – francescalus

+0

嗨,@francescalus然後我會改變第二個到一個固定的格式。但是,是否還需要替換'['到'(/'?因爲OP說他用gfort-4.4編譯,這個'['似乎沒有問題(我用gfortran4.4.7測試過)。 – roygvib

+0

嗯,是否可以重寫這緊湊地沒有使用結構構造函數...?如果我試圖嚴格遵循Fortran77併爲每個元素寫一個賦值,代碼將變得非常冗長...... – roygvib

0

可以構造一個只會被調用一次的例程。例程將從準備好的文件中讀取矩陣的數據。 這肯定會解決你的問題與任何編譯器。