首页 文章

Fortran模块和全局变量

提问于
浏览
2

我正在尝试创建一个可以在主程序和所有子程序中全局访问的数据结构 . 数据结构是通过读取一些.dat文件构建的 .

这种全局可访问性似乎适用于模块 . 到目前为止,我的模块解决方案包括:1)全局定义数据类型; 2)在模块中包含(包含)一堆子程序以打开/读取.dat文件; 3)从.dat文件构造数据类型 .

理想情况下,我想在模块中构建此数据结构ONCE,然后可以全局访问此单个数据结构 . 每次调用模块程序时,我都不想打开/读取.dat文件 .

例如 . 有没有办法将数据结构从主程序声明为全局变量,然后调用模块程序来构建一次数据结构?

@Ross . 源代码:

module DataTypeModule

  implicit none

  type :: DatCube
      integer :: NGrid(4)
      double precision, allocatable :: tgrid(:)
  end type DatCube

  contains

  subroutine DataArraySizes(NGrd)
    implicit none
    integer, intent(out) :: NGrd(4)
    open(unit=15, file='./Data/DataHeader.txt', status='old')
    read(15,*) NGrd(1)
    read(15,*) NGrd(2)
    read(15,*) NGrd(3)
    read(15,*) NGrd(4)
    close(15)
  end subroutine DataArraySizes

  subroutine DataTGrd(NGrd,tgrd)
    implicit none
    integer, intent(in) :: NGrd(4)
    double precision, intent(out) :: tgrd(NGrd(1))
    open(unit=16, file='./Data/tgrid.dat', status='old')
    read(16,*) tgrd
    close(16)
  end subroutine DataTGrd

  subroutine ConstructDataCube(DataCube)
    implicit none
    type(DatCube), Intent(out) :: DataCube

    integer, allocatable :: NGrd(:)
    double precision, allocatable :: tgrd(:)

    allocate( NGrd(4) )
    call DataArraySizes(NGrd)
    DataCube%NGrid = NGrd

    allocate( tgrd(NGrd(1)),DataCube%tgrid(NGrd(1)) )
    call DataTGrd(NGrd,tgrd)
    DataCube%tgrid = tgrd

    deallocate( NGrd,tgrd )

    return
  end

end module DataTypeModule

program main
  use DatatypeModule
  implicit none
  double precision :: arg1,out1(4)
  type(DatCube) :: DataCube

  call ConstructDataCube(DataCube)

  call subrtn1(arg1,out1)

  stop
end


subroutine subrtn1(arg1,out1)
  use DataTypeModule
  implicit none
  double precision, Intent(in)  :: arg1
  double precision, Intent(out) :: out1(4)
  type(DatCube) :: DataCube

  out1 = DataCube%NGrid

  return
end

2 回答

  • 2

    您可以将模块假定为PRIVATE或假定为PUBLIC . 我将展示PRIVATE .

    module DataTypeModule
      implicit none
      PRIVATE                                              !<--
    
      type :: DatCube_Struct
          integer                                           :: nGrid
          double precision, allocatable, DIMENSION(:)       :: tgrid
      end type DatCube_Struct
      !PUBLIC  DatCube_Struct !(Only needs to be public if you want to use it in separate from DataCube)   
      type(DatCube_Struct), DIMENSION(4)           , PUBLIC :: DataCube   !<--
    
      double precision, DIMENSION(:,:), ALLOCATABLE, PUBLIC :: tgrd       !<--
    
      !! PUBLIC DataArraySizes, DataTGrd    !<-- These do not seem to need to be PUBLIC
      PUBLIC ConstructDataCube   !<--
    
    !%%%%%%%%%%%%%%
      contains
    !%%%%%%%%%%%%%%
    
    !%%%%%%%%%%%%%%
    !! subroutine DataArraySizes(NGrd)
    subroutine DataArraySizes
    implicit none
    !!--> integer, intent(out) :: NGrd(4)
    
    open(unit=15, file='./Data/DataHeader.txt', status='old')
    read(15,*) NGrd(1)
    read(15,*) NGrd(2)
    read(15,*) NGrd(3)
    read(15,*) NGrd(4)
    close(15)
    
    RETURN
    end subroutine DataArraySizes
    
    !%%%%%%%%%%%%%%
    subroutine DataTGrd(i)
    implicit none
    integer, intent(in) :: i                      !<--
    !! double precision, intent(out) :: tgrd(i)   !-->  (NGrd(1))
    
    open(unit=16, file='./Data/tgrid.dat', status='old')
    read(16,*) DataCube(I)%tgrid(:)               !<-- Is this grid(1:4)? or a single like #1 tgrd(1)
    close(16)
    
    RETURN
    end subroutine DataTGrd
    
    !%%%%%%%%%%%%%%
    subroutine ConstructDataCube()               !--> (DataCube)
    implicit none
    !!--> type(DatCube)   , Intent(out) :: DataCube   
    !!--> integer         , allocatable :: NGrd(:)
    !!--> double precision, allocatable :: tgrd(:)
    
    !!--> allocate( NGrd(4) )
    call DataArraySizes()      !!--> (NGrd)
    
    do I = 1, UBOUND(nGrd,1)                              !<--
      DataCube(I)%NGrid = NGrd(I)
    ENDDO                                                 !<--
    
    AlloTGrd: do I = 1, UBOUND(nGrd,1)                              !<--
      allocate( tgrd(I ,DataCube(I)%tgrid(NGrd(I)) )
      call DataTGrd(I)
      !!-->  DataCube(I)%tgrid = tgrd(I,:)
    ENDDO AlloTGrd
    
    !!deallocate( NGrd,tgrd )
    
    RETURN
    END subroutine ConstructDataCube
    
    !%%%%%%%%%%%%%%
    end module DataTypeModule
    !%%%%%%%%%%%%%%
    
    PROGRAM main
    USE DatatypeModule
    implicit none
    double precision, PARAMETER    :: arg1 = 1.0D0
    double precision, DIMENSION(4) :: out1
    !!--> type(DatCube) :: DataCube
    
    call ConstructDataCube(DataCube)
    
    call subrtn1(arg1,out1)
    
    !Why stop ?  stop
    end PROGRAM main
    
    !%%%%%%%%%%
    subroutine subrtn1(arg1,out1)
    use DataTypeModule
    implicit none
    double precision              , Intent(in   ) :: arg1
    double precision, DIMENSION(4), Intent(  out) :: out1
    !!--> type(DatCube) :: DataCube
    
    out1 = DataCube(Arg1)%NGrid   !!<-- ??
    
    return
    end subroutine subrtn1
    

    这个“答案”更多的是给你一些想法,而不是一个权威的编译“答案” . 由于数据看起来像是要共享的,我将它们放入标记为PUBLIC的MODULE中 .

  • -1

    一次读取并多次访问的数据非常常见 . 这是一个如何工作的简单示例 . 模块 my_data 包含要存储的数据 x,i 和从磁盘 read_data 读取该数据的子程序 . 应该调用一次读取,并且可以从主程序和子程序多次访问数据 . 在源文件 main.f90 中:

    module my_data
       implicit none
    
       real :: x
       integer :: i
    
    contains
    subroutine read_data
       integer :: fid
    
       open(newunit=fid,file='config.txt',action='read',position='rewind')
    
       read(fid,*) x
       read(fid,*) i
    
       close(fid)
    end subroutine read_data
    end module my_data
    
    module routines
       implicit none
    
    contains
    subroutine mysub
       use my_data, only : x, i
    
       ! -- Use data again
       write(*,*) 'x and i in subroutine are: ', x, i
    
    end subroutine mysub
    end module routines
    
    program main
       use my_data, only : read_data, x, i
       use routines, only : mysub
       implicit none
    
       ! -- Initialize
       call read_data
    
       ! -- Use data
       write(*,*) 'x and i in main are: ', x, i
    
       ! -- Use data in subroutine
       call mysub
    
    end program main
    

    文件 config.txt 包含要读取的数据 .

    mach5% more config.txt
    1.23
    5
    mach5% ifort main.f90 && ./a.out
     x and i in main are:    1.230000               5
     x and i in subroutine are:    1.230000               5
    

    编辑:这里发生的一个关键部分是 xi 存储在读取模块和主程序都可访问的位置 . 在这个简单的例子中,我选择将它存储在 my_data 中,但可以想象它可能存在于其他地方 . 您发布的示例代码已被删除(请将其编辑到您的问题中), never stores the data you have read . 阅读一次后存储数据至关重要 .

    编辑2:在您编辑的源代码中,您将数据读入主程序中声明的变量 DataCube . 然后,您尝试访问在子例程 subrtn1 中声明的变量 DataCube 中的数据 . These are not the same variable. 您必须声明一次,并从多个位置访问它 . 执行此操作的最佳方法是将其包含在模块中,如我在示例中所示 . 但是,您也可以将其作为参数传递给例程,但这会变得很麻烦 .

相关问题