Fortran:名单+关联不起作用

时间:2014-07-28 07:35:21

标签: fortran associate

我将参数存储在派生类型中,我想在运行时通过名称列表从文件中加载它们。这是代码草图:

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

编译器抱怨option1option2,...尚未声明((iFort) error #6404: This name does not have a type, and must have an explicit type. [OPTION1])。

从名单构造(https://software.intel.com/sites/products/documentation/doclib/stdxe/2013/composerxe/compiler/fortran-mac/GUID-EAC90ABA-859A-4745-B9FC-B8D66B5B6FF0.htm)的描述中我读到了

  

var-list中的每个变量必须由USE或主机关联

访问

我想说的是这里的情况,因为thisintent(inout)的伪参数。这不是使用协会吗?

有什么问题?是否有一种解决方法,以至于我不必在不同的地方多次声明相同的东西?

(例如,将option1声明为私有模块,并在this例程末尾的load_options中将其复制而不是使用associate结构,但是我会更喜欢稍后添加选项时不太容易遗漏的内容)

提前感谢任何评论。

PS:就在发布之前我找到了this question。代码看起来可能正在做我想要的但没有看到unit类型的定义我无法理解它的作用。

EDIT1:跟进弗拉基米尔的评论 现在我完全明白发生了什么。在我链接的问题中,作者使用指向this的指针而不是单个字段,如果我可以使其工作,这将是我的首选选项。当我尝试它时,编译器对名单声明很好,但拒绝从输入文件中读取

  

错误#5498:可分配或指针派生类型字段需要用户定义的I / O过程。      读取(111,NML = options_nml,iostat的= IOS,IOMSG = err_message)

有什么建议这样的I / O程序是什么样的?我很困惑,如果可以在名单列表声明中添加派生类型(或指向它的指针),那么我会假设输入文件中的变量应该被称为this%option1,那将是它。我找到了另一个讨论here来自英特尔的史蒂夫莱昂内尔支持这种观点

  

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)语句中发生错误。所以我做的是使用指向名单声明中的结构的指针。这就是全部了。

1 个答案:

答案 0 :(得分:1)

对于ifort,您实际上可以使用我链接的答案中的解决方案。 unit的确切定义在那里并不重要。

select type(t => this)
  type is (opts)

    associate( option1    => t%option1, &
               option2    => t%option2)

      namelist /options_nml/ option1, option2

      read...
    end associate
end select

这是因为this在您的示例中是多态的。

我调查过,这种用法是否符合标准,但事实并非如此。当被要求遵循标准时,Ifort明确警告

ifort -stand f08  namelist.f90
namelist.f90(8): warning #7775: Placement of NAMELIST statement is non-standard.

您还可以执行许多其他解决方法。您可以创建本地指针并在名单列表中读取它们,这正是您链接的答案。那也可以用gfortran编译。我会这样走。

integer, pointer :: option1, option2

namelist /options_nml/ option1, option2

option1 => this%option1
option2 => this%option2

read...

或者使用普通的局部变量并将值复制到this