Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Variables Fortran模块和全局变量_Variables_Module_Fortran_Global - Fatal编程技术网

Variables Fortran模块和全局变量

Variables Fortran模块和全局变量,variables,module,fortran,global,Variables,Module,Fortran,Global,我正在尝试创建一个可以全局访问主程序和所有子例程的数据结构。数据结构是通过读取一些.dat文件构建的 这种全局可访问性似乎适合于模块。到目前为止,我的模块解决方案包括:1)全局定义数据类型;2) 在模块中包括(包含)一组子程序以打开/读取.dat文件;3)从.dat文件构造数据类型 理想情况下,我希望在模块中构建此数据结构一次,然后使此单一数据结构可以全局访问。我不希望每次调用模块过程时都打开/读取.dat文件 比如说。是否有方法将数据结构声明为主程序中的全局变量,然后调用模块过程构建一次数据结

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

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

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

比如说。是否有方法将数据结构声明为主程序中的全局变量,然后调用模块过程构建一次数据结构

@罗斯。源代码:

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

一次读取和多次访问的数据非常常见。下面是一个简单的例子,说明这是如何工作的。模块
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
编辑:这里发生的一个关键部分是
x
i
存储在阅读模块和主程序都可以访问的地方。在这个简单的示例中,我选择将其存储在
my_data
中,但可以想象它可能在其他地方。您发布的示例代码已被删除(请将其编辑到您的问题中),从不存储您阅读的数据。在读取数据一次后存储数据是至关重要的


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

您可以将该模块假定为私有模块或假定为公共模块。我会带你去的

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
模块数据类型模块
隐式无
私有的分配(NGrd(4))
调用DataArraySizes()!!-->(NGrd)
I=1,UBOUND(nGrd,1)!类型(DatCube)::DataCube

out1=DataCube(Arg1)%NGrid!!我不明白你困惑的根源。为什么不在程序开始时调用
read_data
一次,然后
使用来自任何地方的变量呢?@Ross。每次我调用模块过程(从主程序或各种子例程),它都会打开/读取.dat文件并构造数据结构。这是一个巨大的时间水槽。我想调用模块过程(构造数据结构)一次,并将此数据结构设置为主程序和所有子例程可访问的全局变量。我不想将此数据结构作为参数传递给每个子例程,因为我有许多嵌套过程。好吧,这是以前发布的源代码的不同版本,但它看起来更小,所以这很好。@Ross。这里的要点是:我想从.dat文件构造一个全局可访问的数据结构。我不想将该数据结构作为参数传递给从主程序调用的(嵌套)子例程过程。我不想每次调用模块子程序时都阅读.dat文件。我已经阅读并理解了您的问题。请阅读并尝试理解答案。在您的示例中,从主程序调用的(嵌套)子例程是否可以访问数据x,i,而不将x和i作为参数传递?@jkedmond,前提是它们可以访问相应的模块。@VladimirF。你的意思是,只要我在特定的子例程中添加声明“仅使用我的数据:读取数据,x,I”,我就不必将x和I作为参数传递?为什么要调用读取???你不必这么做。他们与访问
x
i
无关……请耐心等待。我对堆栈交换和FORTRAN编程都是新手。