固定格式的Fortran分配数组,其大小要从文件中读取

时间:2018-07-06 02:00:49

标签: arrays fortran dimension intel-fortran

我正在从一个包含值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子例程中。分配语句位于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的已知大小进行分配,否则它们将不会真正使用,但是编译器一直在给我问题。

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

现在,错误提示:

  

如果实际参数为标量,则伪参数应为标量   除非实际参数的类型为character或为   未假定形状,指针或多态的数组。

我编辑了问题,以提供更多代码并阐明我的问题。

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

谢谢!

杰西

1 个答案:

答案 0 :(得分:3)

处理您描述的问题的最安全的方法似乎是让read_file处理分配,即,将exec sp_executesql N'SELECT [Extent1].[ProductId] AS [ProductId], [Extent1].[ManufacturerId] AS [ManufacturerId], [Extent1].[Title] AS [Title] FROM [dbo].[Products] AS [Extent1] WHERE [Extent1].[ManufacturerId] = @p__linq__0',N'@p__linq__0 int',@p__linq__0=3 传递给read_file作为

public static Expression<Func<TItem, bool>> PropertyEqual<TItem, TValue>(
    this PropertyInfo property, TValue value)
{
    var param = Expression.Parameter(typeof(TItem));
    var body = Expression.Equal(Expression.Property(param, property),
        Expression.Constant(value, typeof(TValue)));
    return Expression.Lambda<Func<TItem, bool>>(body, param);
}

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

在读入A,B,C之后,您可以在read_file中分配intent(out)

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

A,B,C

,您可以将其传递给read_file的第一个调用(允许使用0大小的数组,只需确保您不尝试访问其条目即可)。如果我理解正确,则第一个调用将不会对T进行任何操作,仅需要在随后的read_file调用中分配它们。如果是这样,在main.for中分配也可以。

获得T后,您可以使用以下方式重新分配A,B,C

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

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