Фортран: список имен + партнер не работает

Я храню параметры в производном типе и хочу загрузить их из файла через список имен во время выполнения. Это набросок кода:

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]).

Из описания конструкции списка имен ( https://software.intel.com/sites/products/documentation/doclib/stdxe/2013/composerxe/compiler/fortran-mac/GUID-EAC90ABA-859A-4745-B9FC-B8D66B5B6FF0.htm) читаю

каждая переменная в var-list должна быть доступна USE или ассоциацией хоста

который я бы сказал, дело здесь как this это фиктивный аргумент с intent(inout), Разве это не ассоциация использования?

Что случилось? Есть ли обходной путь, чтобы мне не приходилось объявлять одни и те же вещи много раз в разных местах?

(например, объявление option1 как частный модуль и копировать его в this в конце load_options рутина, а не с помощью associate Конструкция будет работать, но я бы предпочел что-то менее склонное к упущениям при добавлении опций позже)

Заранее спасибо за любые комментарии.

PS: незадолго до публикации я нашел этот вопрос. Код выглядит так, как будто он может делать то, что я хочу, но не видя определения unit типа я не могу понять что он делает.

EDIT1: следить за комментариями Владимира Теперь я вполне понимаю, что происходит. В вопросе, на который я ссылался, автор использует указатель на this не для отдельных полей, и это было бы моим предпочтительным вариантом, если бы я мог заставить его работать. Когда я попробовал это, компилятор был в порядке с объявлением списка имен, но отказался читать из входного файла, говоря

ошибка #5498: для выделенных полей или полей производного типа указателя требуется определенная пользователем процедура ввода-вывода. чтения (111,NML=options_nml, IOSTAT = ИОС, iomsg = err_message)

Любые предложения, как такая процедура ввода / вывода может выглядеть? Я запутался, если возможно добавить производный тип (или указатель на него) в объявлении списка имен, то я бы предположил, что переменные во входном файле должны называться как this%option1 и это было бы это. Я нашел другое обсуждение здесь, где Стив Лайонел из Intel поддерживает эту точку зрения, говоря

Стандарт 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 ответ

Решение

Для 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,

Другие вопросы по тегам