2

我正在尝试在模块中编写一个子例程,我可以将其包含在各种代码中以从给定文件中读取数据。我有几个代码(数值算法)将从文件中读取数据。

该文件具有以下格式:

第一项:我的数据数组的行数和列数(例如 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

其中第一个条目表示它是一个 2x2 矩阵和 2x1 向量前 4 行是矩阵 A 的四个条目(左列 Real,右列 Imag。)最后两行是向量 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 Mark 的见解,我编辑了我的代码,这产生了正确的结果,但是如果有任何命令可能导致以后出现问题(例如,我将使用非常大的数组)我会非常感谢听到他们的消息!

   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    )
4

2 回答 2

2

高性能标记已经确定了重大问题,其他一些说明......

  • 您更新代码中的格式规范建议数字之间有两个空格。您的示例输入建议一个 - 请注意第二个数字上的(可选)前导符号!

  • A并且b是可分配的虚拟参数。这是 Fortran 2003 广泛支持且非常有用的功能。你已经远远超过了 Fortran 90!如果那是无意的,那么您将需要认真重新设计事物,否则...

  • 超越 Fortran 90 是一件好事 - Fortran 95(这是所有当前主流 Fortran 编译器提供的最低标准支持级别 - Fortran 90 实际上已过时)和 Fortran 2003 通过扩展修复了 Fortran 90 中的严重缺陷 - 从 Fortran执行过程的 return 或 end 语句时,会自动释放 95 个本地可分配对象。因此,您最后的 deallocate 语句是无害的,但也是多余的。

  • 您将每个复数的分量读入双精度(请注意,现代 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
于 2013-02-18T01:30:52.283 回答
1

你的代码让我很困惑。 声明SUBROUTINE matrix_input数组Aballocatable. intent(out)就在END SUBROUTINE声明之前,您继续并取消分配它们。您希望子例程返回调用例程什么?

于 2013-02-17T18:28:16.090 回答