Fortran模块和全局变量

时间:2017-05-27 15:55:26

标签: variables module fortran global

我试图创建一个全局可访问的主程序和所有子程序的数据结构。数据结构是通过读取一些.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 个答案:

答案 0 :(得分:2)

一次读取并多次访问的数据非常常见。这是一个如何工作的简单示例。模块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中,但可以想象它可能在其他地方。您发布的示例代码已被删除(请将其编辑到您的问题中),从不存储您已阅读的数据。阅读一次后存储数据至关重要。

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

答案 1 :(得分:-1)

您可以将模块假定为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

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