fortran90中的动态数组分配 [英] Dynamic array allocation in fortran90

查看:327
本文介绍了fortran90中的动态数组分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在fortran90中编写一个通用子例程,该子例程将读取一列数据(实际值)。子例程应首先检查文件是否存在并可以打开,然后通过读取直到文件末尾的行数来确定列中的元素数(Array_Size)。接下来,子例程将文件倒回开头,读取数据点并将每个数据点分配给一个数组(Column1(n)),并确定数组中最大的元素(Max_Value)。希望该子例程可以编写为完全通用的,并且不需要任何有关文件中数据点数量的先验知识,这就是为什么首先确定元素的数量以便可以动态地使用数组 Column1的原因分配以包含 Array_Size个数据点。将数组传递到主程序后,将其转移到另一个数组,并释放初始动态分配的数组,以便可以对多个其他输入文件重复该例程,尽管此示例仅读取一个数据文件。

I am writing a generic subroutine in fortran90 that will read in a column of data (real values). The subroutine should first check to see that the file exists and can be opened, then it determines the number of elements (Array_Size) in the column by reading the number of lines until end of file. Next the subroutine rewinds the file back to the beginning and reads in the data points and assigns each to an array (Column1(n)) and also determines the largest element in the array (Max_Value). The hope is that this subroutine can be written to be completely generic and not require any prior knowledge of the number of data points in the file, which is why the number of elements is first determined so the array, "Column1", can be dynamically allocated to contain "Array_Size" number of data points. Once the array is passed to the main program, it is transferred to another array and the initial dynamically allocated array is deallocated so that the routine can be repeated for multiple other input files, although this example only reads in one data file.

如下所述,该程序在Intel fortran编译器上可以正常编译;但是,当它运行时,给我带来了严重的错误(174):SIGSEV故障。我在子例程中的allocate语句之前和之后放置了write()语句,并打印了第一个语句 Program works here,但没有打印第二个语句,这表明问题出在在两个write()语句之间的ALLOCATE(Column1(Array_Size))语句。我用-C标志重新编译了该文件并运行了该可执行文件,该文件再次失败并指出严重(408):尝试在未分配时从可分配变量MISC_ARRAY中获取。变量MISC_ARRAY是主程序中的伪变量,这似乎表明编译器希望在主程序而不是子程序中分配数组。如果我静态分配数组,该程序就可以正常工作。为了使程序通用,并且不需要任何有关每个文件大小的知识,需要对其进行动态分配,并且这应该在子程序而非主程序中进行。

As written below, the program compiles just fine on the Intel fortran compiler; however, when it runs it gives me a severe (174): SIGSEV fault. I place the write(,) statements before and after the allocate statement in the subroutine and it prints the first statement "Program works here", but not the second, which indicates that the problem is occurring at the ALLOCATE (Column1(Array_Size)) statement, between the two write(,) statements. I re-compiled it with -C flag and ran the executable, which fails again and states severe (408): "Attempt to fetch from allocatable variable MISC_ARRAY when it is not allocated". The variable MISC_ARRAY is the dummy variable in the main program, which seems to indicate that the compiler wants the array allocated in the main program and not in the subprogram. If I statically allocate the array, the program works just fine. In order to make the program generic and not require any knowledge of the size of each file, it needs to be dynamically allocated and this should happen in the subprogram, not the main program. Is there a way to accomplish this that I am not seeing?

         PROGRAM MAIN
         IMPLICIT NONE
  ! - variable Definitions for MAIN program
         INTEGER :: n
  ! - Variable Definitions for EXPENSE READER Subprograms
         REAL, DIMENSION(:), ALLOCATABLE :: Misc_Array,MISC_DATA
         INTEGER :: Size_Misc
         REAL :: Peak_Misc_Value
  !       REAL :: Misc_Array(365)
         CHARACTER(LEN=13) :: File_Name
        File_Name = "Misc.txt"
        CALL One_Column(File_Name,Size_Misc,Peak_Misc_Value,Misc_Array)
        ALLOCATE (MISC_DATA(Size_Misc))
        DO n = 1,Size_Misc ! Transfers array data
         MISC_DATA(n) = Misc_Array(n)
        END DO
        DEALLOCATE (Misc_Array)
        END PROGRAM MAIN

        SUBROUTINE One_Column(File_Name,Array_Size,Max_Value,Column1)

        IMPLICIT NONE
        REAL, DIMENSION(:), ALLOCATABLE,INTENT(OUT) :: Column1
   !     REAL :: Column1(365)
        REAL, INTENT(OUT) :: Max_Value
        CHARACTER,INTENT(IN) :: File_Name*13
        INTEGER, INTENT(OUT) :: Array_Size
        INTEGER :: Open_Status,Input_Status,n

   ! Open the file and check to ensure it is properly opened
        OPEN(UNIT=100,FILE = File_Name,STATUS = 'old',ACTION = 'READ', &
             IOSTAT = Open_Status)
        IF(Open_Status > 0) THEN
         WRITE(*,'(A,A)') "**** Cannot Open ",File_Name
         STOP
         RETURN
        END IF
   ! Determine the size of the file
        Array_Size = 0
        DO 300
        READ(100,*,IOSTAT = Input_Status)
        IF(Input_Status < 0) EXIT
        Array_Size = Array_Size + 1
   300  CONTINUE
        REWIND(100)
        WRITE(*,*) "Program works here"
        ALLOCATE (Column1(Array_Size))
        WRITE(*,*) "Program stops working here"
        Max_Value = 0.0
        DO n = 1,Array_Size
         READ(100,*) Column1(n)
         IF(Column1(n) .GT. Max_Value) Max_Value = Column1(n)
        END DO
        END SUBROUTINE One_Column


推荐答案

这是有根据的猜测:我认为子例程 One_Column 应该具有显式接口。如所写,源代码有2个编译单元,一个程序(称为 main )和一个外部子例程(称为 One_Column ) 。

This is an educated guess: I think that the subroutine One_Column ought to have an explicit interface. As written the source code has 2 compilation units, a program (called main) and an external subroutine (called One_Column).

在编译时,编译器无法找出从程序中调用子例程的正确方法。在旧版本(强调旧版本)的Fortran风格中,它需要进行一次信念上的飞跃,然后将其留给链接器以找到具有正确名称的子例程,然后交叉手指(如过去一样),并希望实际参数与虚拟参数匹配在运行时。这种方法不适用于返回分配的数据结构的子例程。

At compile-time the compiler can't figure out the correct way to call the subroutine from the program. In good-old (emphasis on old) Fortran style it takes a leap of faith and leaves it to the linker to find a subroutine with the right name and crosses its fingers (as it were) and hopes that the actual arguments match the dummy arguments at run-time. This approach won't work on subroutines returning allocated data structures.

简单地将 end program 移至源文件的末尾,在空出的行中输入关键字包含。然后,编译器将负责创建必要的接口。

For a simple fix move end program to the end of the source file, in the line vacated enter the keyword contains. The compiler will then take care of creating the necessary interface.

要获得更可扩展的修复,请将子例程放入 module 并将其与之关联。

For a more scalable fix, put the subroutine into a module and use-associate it.

这篇关于fortran90中的动态数组分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆