【问题标题】:Fixed form Fortran Allocate array with size to be read from file固定形式的 Fortran 分配数组,其大小可从文件中读取
【发布时间】:2018-07-06 02:00:48
【问题描述】:

我正在从一个包含值 T 的文件中读取,该值将用于初始化几个数组,这些数组将 T 作为第一个维度,稍后进行分配。即

subroutine read_file(T,F,array,A,B,C,...)
    ...
    real, intent(out) :: T,F
    real, intent(in) :: A,B,C
    real, intent(out) :: array
    ...
    read(1,*) T
    ...
    read(1,*) F
    ...
    read(1,*) array(1), array(5), array(6)
    read(1,*) array(2), array(4)
    read(1,*) array(3)
    ...
    if (F.eq.1) then
        array(1) = A(1)
        array(2) = B(2)
        array(3) = C(3)
    endif
    ...
program main
    ...
    do I=1,nproc
        ...
        do J=1,nsteps
            ...
            call read_file(T,F,array,A,B,C,...)
            ...
        enddo
        ...
        if (F.eq.1.and.etc.) then
            ...
            allocate(A(T,3))
            allocate(B(T,6))
            allocate(C(T))
            ...
        endif
        ...
    enddo

read 语句包含在 modules.for 模块中的 read_file 子例程中。 allocate 语句在 main.for 中,其中 read_file 也被调用。

子例程 read_file 还读取许多其他内容,并且在 1 次代码执行过程中被多次调用,其中某些文件的 T 可能为零。

我需要将 A、B 和 C 传入 read_file。根据同样在 read_file 中读取的标志 F 的条件,需要将 A、B 和 C 中的值分配给 array(1,6),否则将直接从文件中读取。

所以我想我的问题是:如何传入可能未分配大小的数组?我已经在代码中编写了检查以确保 A、B 和 C 不会被实际使用,除非它们以用户输入 T 给出的已知大小进行分配,但编译器一直给我问题。

我尝试编译代码,英特尔编译器首先返回错误,指出 A、B、C 的类型未在 read_file 中声明,因此我在 read_file 中使用 T 和 real :: A(T,3) 声明它们。然后它说由于 T 是 intent(out),它不能用于给 A、B 和 C 赋予维度,因为它们是 intent(in)。所以我从 T 中删除了intent(out)(因为它现在只是real :: T)。

现在,错误提示:

如果实际参数是标量,则虚拟参数应该是标量 除非实际参数是字符类型或者是 不是假定形状、指针或多态的数组。

我编辑了我的问题以提供更多代码并澄清我的问题。

感谢回答和评论的人,我现在知道我可以在子例程中将变量声明为可分配的,这应该可以解决我的问题。

谢谢!

杰西

【问题讨论】:

  • 天啊,我很难理解你的问题。您能否更清楚一些并输入一些最少的代码? (见minimal reproducible exampleHow to Ask
  • Fixed-form 与您的问题无关。您实际上可以在您的子例程中分配ABC。将接口更改为real, intent(out), allocatable :: a(:,:), b(:,:), c(:),然后在您的子程序中读取T 后分配变量。您可能会获得intent(out) 将自动释放ABC 的附带好处。
  • "所以我使用 T 和 real :: A(T,3)" 声明了它们。你在哪里声明的?您是否在 read_file 中编写一个接收数组 A、B、C 作为参数的过程?如果是这样,您不能将它们作为显式形状 (A(T,3)) 传递,而是将它们作为假定形状 (A(:,:)) 传递吗?
  • @evets 我明白了,我绝对可以使用 allocatable 然后我可以在标志打开时分配它。
  • @RodrigoRodrigues 是的,我当时在子例程中声明了 real :: A(T,3) 因为我不知道还能做什么。所以我可以将它们作为假定形状传递?那太好了

标签: arrays fortran dimension intel-fortran


【解决方案1】:

似乎处理你描述的问题最安全的方法是让 read_file 处理分配,即将A,B,C 传递给 read_file as

real, intent(inout), allocatable :: A(:,:), B(:,:), C(:,:) 

使用intent(inout) 允许您使用相同的A,B,C 多次调用read_file,而不会丢失之前调用的信息。如果不需要,请随意使用intent(out)。将未分配的数组作为参数传递是可以的,只需确保在尝试任何访问之前进行分配。

然后您可以在读入T 之后,在read_file 中分配A,B,C

如果无法使用 read_file 进行调整,或者您希望在 main 中进行分配,您也可以使用您描述的方法。首先,将 A,B,C 分配为虚拟数组

allocate(A(0,0), B(0,0), C(0,0)) 

您可以将其传递给 read_file 的第一次调用(允许使用 0 大小的数组,只要确保您不要尝试访问它们的条目)。如果我理解正确,第一次调用不会对A,B,C 执行任何操作,它们只需要在后续调用 read_file 时分配。如果是这种情况,在 main.for 中分​​配也可以。

一旦你获得了T,你可以重新分配A,B,C与

if(allocated(A)) deallocate(A)
allocate(A(T,3))

然后您可以将重新分配的数组传递给 read_file 的下一次调用。

【讨论】:

  • 总而言之,我可以做到以下几点: 1. 预分配为 0,0 维数组,只要确保它们不被使用,除非实际分配。 2. 将 A,B,C 声明为可分配并在 read_file 中分配它们,但如果已分配则需要释放。 3. 将它们声明为假定形状。
  • 一个问题:如果我解除分配,我认为它会删除内容。如果我不解除分配并再次分配会怎样?
  • 抱歉,还有一个问题:intent(inout), allocatable 如果 A、B 和 C 的内容带有值并且已经正确分配,它们会删除它们吗?
  • 更正,如果您解除分配,内容将被删除。如果你试图分配一个已经分配的数组,将会抛出一个错误,所以请确保你先解除分配。
  • intent(inout), allocatable传递时,调用read_file时内容不会被擦除,分配也不会改变
猜你喜欢
  • 1970-01-01
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
相关资源
最近更新 更多