我将参数存储在派生类型中,并且我想在运行时通过名称列表从文件中加载它们。这是代码的草图:
module options_definitions
implicit none
type :: opts
integer :: option1
integer :: option2
contains
procedure :: load => load_options
end type opts
contains
subroutine load_options(this,path_to_profiles_folder,profile_name)
class(opts), intent(inout) :: this
character(len=*), intent(in) :: path_to_profiles_folder
character(len=*), intent(in) :: profile_name
integer :: err, ios
logical :: file_exists
character(len=255) :: err_message
character(len=255) :: path_to_profile_folder
ASSOCIATE( option1 => this%option1, &
option2 => this%option2)
namelist /options_nml/ option1, option2
! the following is INESSENTIAL added for completeness
!-----------------------------------------------------
path_to_profile_folder=trim(path_to_profiles_folder)//trim(profile_name)
! load options from the configuration file (namelist set above)
INQUIRE(FILE=trim(path_to_profile_folder)//'/'//trim(opt_file_name), EXIST=file_exists) ! 'file_exists' will be TRUE if the file exists and FALSE otherwise
if (file_exists) then
call my_open(111,trim(path_to_profile_folder)//'/'//trim(opt_file_name),&
'Options module could not open the options configuration file')
read(111,NML=options_nml,iostat=ios,iomsg=err_message)
call check_read_success_and_close(111,trim(path_to_profile_folder)//'/'//trim(opt_file_name),ios,err_message,&
'Options module could not read from the options configuration file')
else
print*,'Warning: The required configuration file containing options &
(options.nml) does not exist. The inbuilt options will be &
used instead.'
endif
!---------------------------------------
end associate
end subroutine load_options
编译器抱怨option1
, option2
, ... 没有被声明 ( (iFort) error #6404: This name does not have a type, and must have an explicit type. [OPTION1]
)。
var-list 中的每个变量都必须由 USE 或主机关联访问
我想说的是这里的情况,因为this
是intent(inout)
. 这不是使用协会吗?
怎么了?有没有一种解决方法,我不必在不同的地方多次声明相同的东西?
(例如,声明为私有模块并在例程结束时option1
将其复制而不是使用该构造会起作用,但我更喜欢稍后添加选项时不太容易遗漏的东西)this
load_options
associate
提前感谢您的任何评论。
PS:就在发布之前,我发现了这个问题。代码看起来可以做我想做的事,但没有看到unit
类型的定义,我无法理解它的作用。
EDIT1:跟进弗拉基米尔的评论现在我很明白发生了什么。在我链接的问题中,作者使用了一个指向this
不指向单个字段的指针,如果我能让它工作,这将是我的首选。当我尝试它时,编译器对名称列表声明很好,但拒绝从输入文件中读取说
错误 #5498:可分配或指针派生类型字段需要用户定义的 I/O 过程。读取(111,NML=options_nml,iostat=ios,iomsg=err_message)
任何建议这样的 I/O 过程可能是什么样的?我很困惑,如果可以在名称列表声明中添加派生类型(或指向它的指针),那么我会假设输入文件中的变量应该被称为this%option1
,就是这样。我在这里找到了另一个讨论,来自英特尔的史蒂夫莱昂内尔支持这种观点,他说
Fortran 标准只允许在名称列表对象列表中使用“变量名称”。但是,您可以将 T 放入名单中,并在名单输入中引用 T%I(并显示在输出中)。
但是编译器甚至没有看到文件就抱怨。
EDIT2:我在上面的代码中所做的更改(导致第一次编辑时出现编译器错误)是这样的:
class(opts), intent(inout), target :: THIS
TYPE(opts), POINTER :: THIS_NML
namelist /options_nml/ THIS_NML
THIS_NML => THIS
删除了关联构造,删除了原始名单声明。错误发生在块中的read
语句中if (file_exists)
。所以我所做的是在名称列表声明中使用指向结构的指针。就这些。