パラメータを派生型に格納し、実行時に名前リストを介してファイルからロードしたいと考えています。これはコードのスケッチです:
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]
) と文句を言います。
namelist コンストラクトの説明から ( 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: Vladimir のコメントのフォローアップ 今、私は何が起こっているのかをよく理解しています。私がリンクした質問では、作成者はthis
個々のフィールドではなくポインターを使用しています。これを機能させることができれば、これが私の好ましいオプションです。私が試したとき、コンパイラは名前リスト宣言で問題ありませんでしたが、入力ファイルからの読み取りを拒否しました
エラー #5498: 割り当て可能またはポインター構造型フィールドには、ユーザー定義の I/O プロシージャが必要です。read(111,NML=options_nml,iostat=ios,iomsg=err_message)
そのような I/O 手順がどのように見えるかについて何か提案はありますか? 名前リスト宣言に派生型(またはそれへのポインター)を追加できる場合、入力ファイル内の変数を参照する必要があり、それthis%option1
がそれであると想定します。ここで、インテルのスティーブ・ライオネルがこの見解を支持している別の議論を見つけました。
Fortran 標準では、namelist オブジェクト リストで「変数名」のみが許可されます。ただし、名前リストに 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)
そこで私がしたことは、namelist 宣言で構造体へのポインターを使用することでした。それだけでした。