我试图创建一个全局可访问的主程序和所有子程序的数据结构。数据结构是通过读取一些.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
答案 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
编辑:这里发生的一件重要事情是x
和i
存储在阅读模块和主程序都可以访问的地方。在这个简单的例子中,我选择将它存储在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中。