2013-02-17 640 views
1

我試圖在一個模塊中編寫一個子程序,我可以在各種代碼中包含這些子程序以讀取給定文件中的數據。我有幾個代碼(數值算法),它們將從文件中讀取數據。從FORTRAN90的TXT文件中讀取複雜數組和向量

該文件具有以下格式:

第一條目:我的數據的陣列的行和列(例如,720)

第一N(= 720)的條目號:的整個第一行矩陣A 第二N(= 720)輸入:矩陣的整個第二行A

最後N(= 720)輸入:矢量b的所有n個條目

每個條目都有兩列,一列用於編號的REAL部分,另一列用於COMPLEX部分。

綜上所述,示例基本輸入文件:

2 
    -0.734192049E+00 0.711486186E+01 
    0.274492957E+00 0.378855374E+01 
    0.248391205E-01 0.412154039E+01 
    -0.632557864E+00 0.195397735E+01 
    0.289619736E+00 0.895562183E+00 
    -0.284756160E+00 -0.892163111E+00 

其中第一項表示它的一個2×2矩陣和2×1向量 第4行是矩陣A的四個條目(左列實,右邊列Imag) 最後2行是向量b的兩個條目(左列Real,右列Imag)。 我已經寫了下面的代碼來嘗試並實現此操作,但它只是輸出錯誤的結果:

n=   2 
    A= ( 0.0000000 , 1.08420217E-19) (-9.15983229E-16, 3.69024734E+19) (1.26116862E-43, 0.0000000 ) ( 0.0000000 , 0.0000000 ) 
    b= ( 0.0000000 , 1.08420217E-19) ( 0.0000000 , 1.08420217E-19) 

隨着代碼:

SUBROUTINE matrix_input(n,A,b) 
IMPLICIT NONE 
! 
INTEGER, INTENT(OUT)         ::n !size of matrix to be read 
COMPLEX, DIMENSION(:,:), INTENT(OUT), ALLOCATABLE  ::A !system matrix to be read 
COMPLEX, DIMENSION(:), INTENT(OUT), ALLOCATABLE  ::b !RHS b vector to be read 
DOUBLE PRECISION          ::A_Re,A_Im,b_Re,b_Im ! 
INTEGER            ::i,j 
!---------------------------------------------------------- 
! Subroutine outputs 'n'=size of matrix, 'A'=system matrix 
! 'b'= RHS vector 
!matrix194.txt 
OPEN (UNIT = 24, FILE = "matrix_input_test.txt", STATUS="OLD", FORM="FORMATTED",  ACTION="READ") 

!Read in size of matrix 
READ(24,*) n 

ALLOCATE(A(n,n)) 
ALLOCATE(b(n)) 

!Read matrix A: 
DO i=1,n 
    DO j=1,n 

    READ(24,*) A_Re, A_Im 
    A(i,j)=CMPLX(A_Re,A_Im) 

    END DO 
END DO 

!Read RHS vector b: 
DO i=((n*n)+1),((n*n)+n) 

    READ(24,*) b_Re, b_Im 
    b(i)=CMPLX(b_Re,b_Im) 

END DO 


CLOSE(UNIT=24) 
DEALLOCATE(A,b) 
END SUBROUTINE matrix_input 

編輯:繼HPC馬克的見解,我已經編輯我的代碼,這會產生正確的結果,但如果有可能導致問題後來就停機的任何命令行(例如我將使用非常大的陣列)我非常感謝他們的消息!

SUBROUTINE matrix_input(n,A,b) 
    IMPLICIT NONE 
    ! 
    INTEGER, INTENT(OUT)         ::n !size of matrix to be read 
    COMPLEX, DIMENSION(:,:), INTENT(OUT), ALLOCATABLE  ::A !system matrix to be read 
    COMPLEX, DIMENSION(:), INTENT(OUT), ALLOCATABLE  ::b !RHS b vector to be read 
    ! 
    COMPLEX, DIMENSION(:), ALLOCATABLE     ::temp,A_temp !temp vector of matrix A 
    DOUBLE PRECISION          ::A_Re,A_Im,b_Re,b_Im 
    INTEGER            ::i,j,k 
    !---------------------------------------------------------- 
    ! Subroutine outputs 'n'=size of matrix, 'A'=system matrix 
    ! 'b'= RHS vector 
    !matrix194.txt 
    OPEN (UNIT = 24, FILE = "matrix_input_test.txt", STATUS="OLD", FORM="FORMATTED", ACTION="READ") 

    !Read in size of matrix 
    READ(24,*) n 

    !Allocate arrays/vectors 
    ALLOCATE(A(n,n)) 
    ALLOCATE(b(n)) 
    ALLOCATE(temp(n*n+n)) 
    ALLOCATE(A_temp(n*n)) 

    !Read matrix A & vector b: 
    !16 characters, 9 decimal places, exponent notation, 2 spaces 
    DO i=1,(n*n)+n 
     READ(24, FMT="(E16.9, 2X, E16.9)") A_Re, A_Im 
     temp(i)=CMPLX(A_Re,A_Im) 
    END DO 

    !Select A: 
    DO i=1,n*n 
     A_temp(i)=temp(i) 
    END DO 
    !Reshape 
    A=RESHAPE(A_temp, (/n,n/)) 

    !Select b: 
    k=0 
    DO i=n*n+1,n*n+n 
     k=k+1 
     b(k)=temp(i) 
    END DO 

    CLOSE(UNIT=24) 
    !Do not deallocate A & b otherwise won't return anything properly 
    DEALLOCATE(temp, A_temp) 
    END SUBROUTINE matrix_input 

結果從編輯的代碼:

n=   2 
    A= (-0.73419207 , 7.1148620 ) (0.27449295 , 3.7885537 ) (0.24839121 , 4.1215405 ) (-0.63255787 , 1.9539773 ) 
    b= (0.28961974 , 0.89556217 ) (-0.28475615 ,-0.89216310 ) 

回答

0

您的代碼混淆了我。 SUBROUTINE matrix_input宣佈陣列Aballocatableintent(out)。就在END SUBROUTINE聲明之前,您可以立即前進並釋放它們。你期望子程序返回到調用例程?

+0

我要補充一點,我有點一個Fortran新手,所以你的代碼混亂,語句是完全有效的 - 謝謝!這實際上幫助我解決了這個問題! – user2016338 2013-02-17 22:31:36

+0

我編輯的結果代碼如上。 – user2016338 2013-02-17 22:42:20

1

高性能馬克已經確定的顯著問題,其他一些筆記...

  • 你的格式規範在您更新的代碼顯示在數字之間兩個空格。您的示例輸入提示一個 - 請注意第二個數字上的(可選)前導符號!

  • Ab是可分配的虛擬參數。這是一個廣泛支持和非常有用的Fortran 2003功能。你遠遠超過了Fortran 90!如果這是無意的,那麼你將需要認真重新設計的東西,否則...Fortran 95(這是目前所有主流Fortran編譯器提供的最低級別的標準支持--Fortran 90實際上已經過時),而Fortran 2003的擴展確定了Fortran嚴重缺陷90 - 自Fortran 95起,當執行過程的return或end語句時,會自動釋放95個本地可分配對象。最終你的釋放聲明是無害的,但是是多餘的。

  • 您閱讀每個複數爲雙精度的部件(注意用現代的Fortran公共源代碼風格趨於避免DOUBLE PRECISION類型說明符 - 它只是REAL(KIND(0.0D0))的代名詞)。然後將它們存儲到默認(單精度)複合體中。那是故意的嗎?如果是這樣,它是無害的,但有點沒有意義/不一致,否則,如果您打算以更高的精度存儲輸出數組中的實數和虛數分量,那麼您需要適當地更改複數數組的聲明。 REAL的所有種類必須可用於COMPLEX,因此您的聲明可能是COMPLEX(KIND(0.0D0))(通常您會擁有一種命名常量)。

  • 在輸入輸出列表中,一個複雜的標量變量表示兩個有效項目 - 實部​​和虛部。因此,您的雙精度變量A_ReA_Im等,有點多餘...... READ(24, FMT="(E16.9, 2X, E16.9)") temp(i)是所有需要的。

  • 個人而言,我不會與其他臨時陣列打擾 - 一旦你知道輸入數據的大小(第一行)分配你AB陣列所需的大小,直接讀入他們。在一個io列表中,一個數組以數組元素的順序展開爲其元素(第一個下標變化最快) - 這似乎是您的文件排列方式。您可以將其與所謂的格式反轉結合起來,以消除循環的需要。

  • 從子程序返回時,可分配數組「知道」它們的形狀 - 不需要單獨返回這些信息。再次,無害但多餘。

結果 - 我想你的整個子程序可能類似於:

! Read A and B in from a file that has... etc, etc... 
! Assuming a module procedure, where the module already has IMPLICIT NONE. 
SUBROUTINE matrix_input(A, b) 
    ! Number of rows and columns of A, elements of B. 
    INTEGER :: n 
    ! Our output data. 
    COMPLEX(KIND(0.0D0)), INTENT(OUT), ALLOCATABLE :: A(:,:), b(:) 
    ! Number of the logical unit for IO. In F2008 this becomes a variable 
    ! and you use the NEWUNIT specifier. 
    INTEGER, PARAMETER :: unit = 24 
    ! The name of the file to read the data from. 
    CHARACTER(*), PARAMETER :: filename = "matrix_input_test.txt" 
    ! Format for the array and vector component of the data. 
    CHARACTER(*), PARAMETER :: fmt = "(E16.9, 1X, E16.9)" 
    !*****************************************************************************  
    ! Connect to the file for sequential formatted reading. 
    OPEN(unit, FILE=filename, STATUS='OLD', ACTION='READ') 
    READ (unit, *) n   ! Get array dimension. 
    ALLOCATE(A(n,n), b(n))  ! Allocate result arrays. 
    READ (unit, fmt) A   ! Read in A. 
    READ (unit, fmt) b   ! Read in B. 
    CLOSE (unit)    ! Clean up. 
END SUBROUTINE matrix_input