如何在Fortran中初始化大数组? [英] how to initialize a large array in Fortran?

查看:323
本文介绍了如何在Fortran中初始化大数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Fortran函数,我想在编译时初始化一个大数组。下面是一个简化的工作示例,其中 fill_coefficients 中的参数 coeff 的大小已大大减小。

I have a Fortran function in which I would like to initialize a large array at compile time. A simplified working example is below, where the parameter coeff in fill_coefficients has been reduced in size greatly.

coeff 大而又不超过最多255条连续行,或每行最多132个字符?在这里, fill_coefficients 应该确实是 PURE ,这可能使得不可能读取 coeff 在运行时从文件中删除一次,然后存储结果。

How do I write similar code when coeff is large, without exceeding the maximum of 255 continuation lines, or the maximum of 132 characters per line? Here fill_coefficients should really be PURE, which probably makes it impossible to read coeff from a file once during runtime, and then store the result.

文件 main.f03:

The file "main.f03":

    PROGRAM main
        USE coefficients
        IMPLICIT NONE

        REAL(dp), ALLOCATABLE, DIMENSION(:,:) :: matrix

        CALL fill_coefficients(matrix,2)

        PRINT *, "The first row of 'matrix':"
        PRINT *, matrix(1,:)
    END PROGRAM main

文件 coefficients.f03:

The file "coefficients.f03":

    MODULE coefficients
        USE iso_fortran_env
        IMPLICIT NONE

        INTEGER, PARAMETER :: dp = REAL64

    CONTAINS
        PURE SUBROUTINE fill_coefficients(my_coefficients, n)
            IMPLICIT NONE
            REAL(dp), ALLOCATABLE, DIMENSION(:,:), INTENT(OUT) :: my_coefficients
            INTEGER, INTENT(IN) :: n

            ! The size of the following array would be roughly 200 x 200 = 40.000.
            REAL(dp), DIMENSION(3,3), PARAMETER :: coeff = &
                RESHAPE ( &
                [ + 10.6770782520313112108115239655957106_dp, &
                - 854.166260162504896864921917247656850_dp, &
                - 85.4166260162504896864921917247656850_dp, &
                + 16250.5130995916556628551394756366716_dp, &
                + 6747.91345528378868523288314625648912_dp, &
                + 106.770782520313112108115239655957106_dp, &
                - 123256.191341449456617608232658836883_dp, &
                - 8328.12103658442274443298869316465429_dp, &
                + 500381.272281447399894682070647642979_dp ], &
                [3,3] )

            IF (ALLOCATED(my_coefficients)) DEALLOCATE(my_coefficients)
            ALLOCATE(my_coefficients(n,n))

            my_coefficients = coeff(1:n,1:n)
        END SUBROUTINE fill_coefficients
    END MODULE coefficients

输出:

第一行'matrix':
10.677078252031311 16250.513099591655

推荐答案

从维护角度(也许正如注释中所建议),我会将数据读入模块变量中在一个单独的非纯子例程中,该子例程在程序启动时被调用一次。 fill_coefficients 然后成为该模块变量的简单分配,并且仍然可以是PURE。

From a maintenance perspective (and as perhaps suggested in the comments), I would read the data into a module variable in a separate non-pure subroutine that is called once at program start-up. fill_coefficients then becomes a simple assignment from that module variable and can still be PURE.

MODULE coefficients
  IMPLICIT NONE
  ...
  ! Could be PUBLIC, PROTECTED, then you could directly 
  ! assign from it and dispense with fill_coefficients 
  ! altogether.
  REAL(dp), PRIVATE :: coeff(200,200)
CONTAINS
  SUBROUTINE init
    INTEGER :: unit 
    OPEN( NEWUNIT=unit,  &
          FILE='lots-of-numbers.bin',  &
          FORM='UNFORMATTED',  &
!         ACCESS='STREAM',  &    ! Maybe - depending on how you write it.
          STATUS='OLD' )
    READ (unit) coeff
    CLOSE(unit)
  END SUBROUTINE init

  PURE SUBROUTINE fill_coefficients(my_coefficients, n)
    ! implicit none already in force due to the statement in 
    ! the specification part of the host module.
    ! IMPLICIT NONE    
    REAL(dp), ALLOCATABLE, DIMENSION(:,:), INTENT(OUT) :: my_coefficients
    INTEGER, INTENT(IN) :: n

    ! This test is redundant - my_coefficients is INTENT(OUT) so 
    ! it must be not allocated at this point.
    ! IF (ALLOCATED(my_coefficients)) DEALLOCATE(my_coefficients)

    ! This allocate statement is redundant - allocation will 
    ! happen automatically under F2003 with the assignment.
    ! ALLOCATE(my_coefficients(n,n))

    my_coefficients = coeff(1:n,1:n)
  END SUBROUTINE fill_coefficients
END MODULE coefficients

如果必须将 coeff 作为编译时间参数,则将其汇编为源可管理块-也许逐列。每个声明的限制是行长(132)和连续行数(255)。

If you must have coeff as a compile time parameter, then assemble it in source manageable chunks - perhaps column by column. Your limits per declaration are line length (132) and number of continuation lines (255).

REAL(dp), PARAMETER :: column_1(200) = [  &
     + 10.6770782520313112108115239655957106_dp, &
     - 854.166260162504896864921917247656850_dp, &
     - 85.4166260162504896864921917247656850_dp, &
     ... ]
REAL(dp), PARAMETER :: column_2(200) = [ ... ]
...
REAL(dp), PARAMETER :: column_200(200) = [ ... ]

REAL(dp), PARAMETER :: coeff(200,200) = RESHAPE( [  &
       column_1, column_2, ..., column_200 ],  &
     SHAPE=[200,200] )

用PARAMETER声明的东西称为常量。从概念上讲,它们仅在编译时存在-取决于您对命名常量的处理方式,编译器可能会或可能不会在可执行映像中为常量预留存储空间。

Things declared with PARAMETER are named constants. Conceptually these only exist at compile time - depending on what you do with a named constant the compiler may or may not set aside storage in the executable image for the constants.

大命名常量可能会导致编译器在编译文件时遇到问题。

Large named constants may result in the compiler having issues compiling the file.

这篇关于如何在Fortran中初始化大数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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